#ifndef __SCAVENGER__
#define __SCAVENGER__
#define pascal
#include "SRuntime.h"
#include "BTree.h"
#include "BTreePrivate.h"
#include "CheckHFS.h"
#include "BTreeScanner.h"
#include "hfs_endian.h"
#include "../fsck_debug.h"
#include "../fsck_messages.h"
#include "../fsck_hfs_msgnums.h"
#include "../fsck_msgnums.h"
#include "../fsck_hfs.h"
#include <assert.h>
#include <sys/xattr.h>
#include <sys/acl.h>
#include <sys/kauth.h>
#include <sys/errno.h>
#include <sys/syslimits.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <hfs/hfs_mount.h>
#ifdef __cplusplus
extern "C" {
#endif
#define kFSCKMountVersion 0x6673636B
enum {
Log2BlkLo = 9, Log2BlkHi = 23 };
enum {
kNoHint = 0
};
#define DISK_IOSIZE 32768
#define kMaxReScan 3
#define kBTreeHeaderUserBytes 128
#define kBusErrorValue 0x50FF8001
#define kMaxClumpSize 0x100000
#define MDB_FNum 1
#define AMDB_FNum -1
#define VBM_FNum 2
#define MDB_BlkN 2
#define kCalculatedExtentRefNum ( 0 )
#define kCalculatedCatalogRefNum ( 1*sizeof(SFCB) )
#define kCalculatedAllocationsRefNum ( 2*sizeof(SFCB) )
#define kCalculatedAttributesRefNum ( 3*sizeof(SFCB) )
#define kCalculatedStartupRefNum ( 4*sizeof(SFCB) )
#define kCalculatedRepairRefNum ( 5*sizeof(SFCB) )
#define Max_ABSiz 0x7FFFFE00
#define Blk_Size 512
#define kHFSBlockSize 512
#define VAtrb_Msk 0x007F
#define VAtrb_DFlt 0x0100
#define VAtrb_Cons 0x0100
#define kHFSCatalogNodeIDsReused 0x1000
enum {
kTextFileType = 0x54455854,
kTextFileCreator = 0x74747874,
};
enum {
kHFSAliasType = 0x66647270,
kHFSAliasCreator = 0x4D414353
};
#define BTMaxDepth 8
#define Num_HRecs 3
#define Num_MRecs 1
typedef struct BTreeExtensionsRec
{
Ptr BTCBMPtr; UInt32 BTCBMSize; BTreeControlBlock *altBTCB; UInt32 realFreeNodeCount; } BTreeExtensionsRec;
typedef struct STPR {
UInt32 TPRNodeN;
SInt16 TPRRIndx;
SInt16 unused;
UInt32 TPRLtSib;
UInt32 TPRRtSib;
} STPR, *STPRPtr;
typedef STPR SBTPT[BTMaxDepth];
#define LenSBTPT ( sizeof(STPR) * BTMaxDepth )
#define CMMaxDepth 100
#define fNameLocked 4096
union CatalogName {
Str31 pstr;
HFSUniStr255 ustr;
};
typedef union CatalogName CatalogName;
typedef struct SDPR {
UInt32 directoryID; UInt32 offspringIndex; UInt32 directoryHint; long threadHint; HFSCatalogNodeID parentDirID; CatalogName directoryName; } SDPR;
enum {
kDefaultNumMRUCacheBlocks = 16
};
enum {
noCacheBit = 5,
noCacheMask = 0x0020,
rdVerifyBit = 6,
rdVerifyMask = 0x0040
};
enum
{
Is_AppleTalk = 0,
Is_Agent = 1, FollowsNewRules = 2, Is_Open = 5,
Is_Ram_Based = 6,
Is_Active = 7,
Read_Enable = 8,
Write_Enable = 9,
Control_Enable = 10,
Status_Enable = 11,
Needs_Goodbye = 12,
Needs_Time = 13,
Needs_Lock = 14,
Is_AppleTalk_Mask = 1 << Is_AppleTalk,
Is_Agent_Mask = 1 << Is_Agent,
FollowsRules_Mask = 1 << FollowsNewRules,
Is_Open_Mask = 1 << Is_Open,
Is_Ram_Based_Mask = 1 << Is_Ram_Based,
Is_Active_Mask = 1 << Is_Active,
Read_Enable_Mask = 1 << Read_Enable,
Write_Enable_Mask = 1 << Write_Enable,
Control_Enable_Mask = 1 << Control_Enable,
Status_Enable_Mask = 1 << Status_Enable,
Needs_Goodbye_Mask = 1 << Needs_Goodbye,
Needs_Time_Mask = 1 << Needs_Time,
Needs_Lock_Mask = 1 << Needs_Lock
};
enum {
cdInternalErr = -1312, cdVolumeNotFoundErr = -1313, cdCannotReadErr = -1314, cdCannotWriteErr = -1315, cdNotHFSVolumeErr = -1316, cdUnrepairableErr = -1317, cdRepairFailedErr = -1318, cdUserCanceledErr = -1319, cdVolumeInUseErr = -1320, cdNeedsRepairsErr = -1321, cdReMountErr = -1322, cdUnknownProcessesErr = -1323, cdDamagedWrapperErr = -1324, cdIncompatibleOSErr = -1325, cdMemoryFullErr = -1326 };
enum {
fsDSIntErr = -127
};
enum {
kFileSharingEnabled = 0x00000001,
kDiskIsLocked = 0x00000002,
kDiskIsBoot = 0x00000004,
kDiskHasOpenFiles = 0x00000008,
kVolumeHadOverlappingExtents = 0x00000010, kVolumeClean = 0x00000020,
kRepairsWereMade = 0x80000000
};
enum
{
ignoreRunningProcessesMask = 0x00000001, checkDiskVersionMask = 0x00000004 };
enum {
kStatusMessage = 0x0000,
kTitleMessage = 0x0001,
kErrorMessage = 0x0002
};
enum {
kHFSStage = 0,
kRepairStage,
kVerifyStage,
kAboutToRepairStage
};
enum {
rDamagedFilesDirSTRid = -20886
};
enum {
kUnknownVolumeType = 0,
kHFSVolumeType,
kEmbededHFSPlusVolumeType,
kPureHFSPlusVolumeType
};
enum {
kStatusLines = 131,
kFirstError = 500,
kHighLevelInfo = 1100,
kBasicInfo = 1200,
kErrorInfo = 1202,
kErrorBase = -1310
};
typedef struct RepairOrder
{
struct RepairOrder *link;
SInt16 type;
SInt16 forkType;
UInt64 correct;
UInt64 incorrect;
UInt32 maskBit;
UInt32 hint;
UInt32 parid;
unsigned char name[1];
} RepairOrder, *RepairOrderPtr;
typedef struct EmbededVolDescription
{
SInt16 drAlBlSt;
UInt16 drEmbedSigWord;
HFSExtentDescriptor drEmbedExtent;
} EmbededVolDescription;
typedef struct ExtendedDrvQueue
{
char dQVolumeLocked;
char dQDiskInDrive;
char dQUsedInternally;
char dQDiskIsSingleSided;
QElemPtr qLink;
short qType;
short dQDrive;
short dQRefNum;
short dQFSID;
short dQDrvSz;
short dQDrvSz2;
}ExtendedDrvQueue;
typedef struct MissingThread
{
struct MissingThread *link;
UInt32 threadID;
HFSPlusCatalogKey nextKey;
HFSPlusCatalogThread thread;
} MissingThread;
#define kDataFork 0
#define kRsrcFork (-1)
#define kEAData 1
struct ExtentInfo {
HFSCatalogNodeID fileID;
UInt32 startBlock;
UInt32 blockCount;
UInt32 newStartBlock;
char * attrname;
UInt8 forkType;
Boolean didRepair;
};
typedef struct ExtentInfo ExtentInfo;
struct ExtentsTable {
UInt32 count;
ExtentInfo extentInfo[1];
};
typedef struct ExtentsTable ExtentsTable;
struct FileIdentifier {
Boolean hasThread;
HFSCatalogNodeID fileID;
HFSCatalogNodeID parID; Str31 name; };
typedef struct FileIdentifier FileIdentifier;
struct FileIdentifierTable {
UInt32 count;
FileIdentifier fileIdentifier[1];
};
typedef struct FileIdentifierTable FileIdentifierTable;
union ExtentKey {
HFSExtentKey hfs;
HFSPlusExtentKey hfsPlus;
};
typedef union ExtentKey ExtentKey;
union ExtentDescriptor {
HFSExtentDescriptor hfs;
HFSPlusExtentDescriptor hfsPlus;
};
typedef union ExtentDescriptor ExtentDescriptor;
union ExtentRecord {
HFSExtentRecord hfs;
HFSPlusExtentRecord hfsPlus;
};
typedef union ExtentRecord ExtentRecord;
union CatalogKey {
HFSCatalogKey hfs;
HFSPlusCatalogKey hfsPlus;
};
typedef union CatalogKey CatalogKey;
union CatalogRecord {
SInt16 recordType;
HFSCatalogFolder hfsFolder;
HFSCatalogFile hfsFile;
HFSCatalogThread hfsThread;
HFSPlusCatalogFolder hfsPlusFolder;
HFSPlusCatalogFile hfsPlusFile;
HFSPlusCatalogThread hfsPlusThread;
};
typedef union CatalogRecord CatalogRecord;
struct AttributeKey {
UInt16 keyLength;
UInt16 pad;
HFSCatalogNodeID cnid;
UInt32 startBlock;
UInt16 attrNameLen;
UInt16 attrName[127];
};
typedef struct AttributeKey AttributeKey;
enum {
kAttributeKeyMaximumLength = sizeof(AttributeKey) - sizeof(UInt16),
kAttributeKeyMinimumLength = kAttributeKeyMaximumLength - 127 * sizeof(UInt16) + sizeof(UInt16)
};
struct HIOParam {
QElemPtr qLink;
short qType;
short ioTrap;
Ptr ioCmdAddr;
void* ioCompletion;
OSErr ioResult;
StringPtr ioNamePtr;
short ioVRefNum;
short ioRefNum;
SInt8 ioVersNum;
SInt8 ioPermssn;
Ptr ioMisc;
Ptr ioBuffer;
long ioReqCount;
long ioActCount;
short ioPosMode;
long ioPosOffset;
};
typedef struct HIOParam HIOParam;
typedef HIOParam * HIOParamPtr;
struct FCBArray {
UInt32 length;
SFCB fcb[1];
};
typedef struct FCBArray FCBArray;
typedef int (*UserCancelProcPtr)(UInt16 progress, UInt16 secondsRemaining, Boolean progressChanged, UInt16 stage, void *context, int passno);
#if 0
typedef UniversalProcPtr UserCancelUPP;
enum {
uppUserCancelProcInfo = kPascalStackBased
| RESULT_SIZE(kTwoByteCode)
| STACK_ROUTINE_PARAMETER(1, kTwoByteCode)
| STACK_ROUTINE_PARAMETER(2, kTwoByteCode)
| STACK_ROUTINE_PARAMETER(3, kTwoByteCode)
| STACK_ROUTINE_PARAMETER(4, kTwoByteCode)
| STACK_ROUTINE_PARAMETER(5, kFourByteCode)
};
#define NewUserCancelProc(userRoutine) \
(UserCancelUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUserCancelProcInfo, GetCurrentArchitecture())
#define CallUserCancelProc(userRoutine, progress, secondsRemaining, progressChanged, stage, context, p) \
CallUniversalProc((UniversalProcPtr)(userRoutine), uppUserCancelProcInfo, (progress), (secondsRemaining), (progressChanged), (stage), (context), (p))
#else
typedef UserCancelProcPtr UserCancelUPP;
#define NewUserCancelProc(userRoutine) \
((UserCancelUPP) (userRoutine))
#define CallUserCancelProc(userRoutine, progress, secondsRemaining, progressChanged, stage, context, p) \
(*(userRoutine))((progress), (secondsRemaining), (progressChanged), (stage), (context), (p))
#endif
typedef pascal void (*UserMessageProcPtr)(StringPtr message, SInt16 messageType, void *context);
#if 0
typedef UniversalProcPtr UserMessageUPP;
enum {
uppUserMessageProcInfo = kPascalStackBased
| STACK_ROUTINE_PARAMETER(1, kFourByteCode)
| STACK_ROUTINE_PARAMETER(2, kTwoByteCode)
| STACK_ROUTINE_PARAMETER(3, kFourByteCode)
};
#define NewUserMessageProc(userRoutine) \
(UserMessageUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUserMessageProcInfo, GetCurrentArchitecture())
#define CallUserMessageProc(userRoutine, message, messageType, context) \
CallUniversalProc((UniversalProcPtr)(userRoutine), uppUserMessageProcInfo, (message), (messageType), (context))
#else
typedef UserMessageProcPtr UserMessageUPP;
#define NewUserMessageProc(userRoutine) \
((UserMessageUPP) (userRoutine))
#define CallUserMessageProc(userRoutine, message, messageType, context) \
(*(userRoutine))((message), (messageType), (context))
#endif
typedef struct PrimeBuckets {
UInt32 n32[32];
UInt32 n27[27];
UInt32 n25[25];
UInt32 n7[7];
UInt32 n11[11];
UInt32 n13[13];
UInt32 n17[17];
UInt32 n19[19];
UInt32 n23[23];
UInt32 n29[29];
UInt32 n31[31];
} PrimeBuckets;
typedef struct attributeInfo {
Boolean isValid;
Boolean hasSecurity;
int16_t recordType;
u_int32_t fileID;
unsigned char attrname[XATTR_MAXNAMELEN+1];
u_int32_t totalBlocks;
u_int32_t calculatedTotalBlocks;
u_int64_t logicalSize;
} attributeInfo;
enum {
kVO_Inited = 0x00000001, kVO_PriVHBOK = 0x00000002, kVO_AltVHBOK = 0x00000004, kVO_PriMDBOK = 0x00000008, kVO_AltMDBOK = 0x00000010, };
typedef struct VolumeObject {
UInt32 flags;
SVCB * vcbPtr; UInt32 volumeType; UInt32 embeddedOffset; UInt32 sectorSize; UInt64 totalDeviceSectors; UInt64 totalEmbeddedSectors; UInt64 primaryVHB; UInt64 alternateVHB; UInt64 primaryMDB; UInt64 alternateMDB; } VolumeObject, *VolumeObjectPtr;
typedef struct SGlob {
void * scavStaticPtr; SInt16 DrvNum; SInt16 RepLevel; SInt16 ScavRes; OSErr ErrCode; OSErr IntErr; UInt16 VIStat; UInt16 ABTStat; UInt16 EBTStat; UInt16 CBTStat; UInt32 CatStat; UInt16 VeryMinorErrorsStat; UInt16 JStat; UInt16 PrintStat; DrvQElPtr DrvPtr; UInt32 TarID; UInt64 TarBlock; SInt16 BTLevel; SBTPT *BTPTPtr; SInt16 DirLevel; SDPR *DirPTPtr; uint32_t dirPathCount; SInt16 CNType; UInt32 ParID; CatalogName CName; RepairOrderPtr MinorRepairsP; MissingThread *missingThreadList;
Ptr FCBAPtr; UInt32 **validFilesList;
ExtentsTable **overlappedExtents; FileIdentifierTable **fileIdentifierTable;
UInt32 inputFlags;
UInt32 volumeFeatures; Boolean usersAreConnected; Boolean fileSharingOn; UInt32 altBlockLocation;
Boolean checkingWrapper;
SInt16 numExtents; OSErr volumeErrorCode;
UserCancelUPP userCancelProc;
UserMessageUPP userMessageProc;
void *userContext;
UInt64 onePercent;
UInt64 itemsToProcess;
UInt64 itemsProcessed;
UInt64 lastProgress;
long startTicks;
UInt16 secondsRemaining;
long lastTickCount;
SVCB *calculatedVCB;
SFCB *calculatedExtentsFCB;
SFCB *calculatedCatalogFCB;
SFCB *calculatedAllocationsFCB;
SFCB *calculatedAttributesFCB;
SFCB *calculatedStartupFCB;
SFCB *calculatedRepairFCB;
BTreeControlBlock *calculatedExtentsBTCB;
BTreeControlBlock *calculatedCatalogBTCB;
BTreeControlBlock *calculatedRepairBTCB;
BTreeControlBlock *calculatedAttributesBTCB;
Boolean cleanUnmount;
Boolean guiControl;
fsck_ctx_t context;
int chkLevel;
int repairLevel;
int rebuildOptions; Boolean minorRepairErrors; Boolean minorRepairFalseSuccess; int canWrite; int writeRef; int lostAndFoundMode; int liveVerifyState; BTScanState scanState;
int scanCount;
unsigned char volumeName[256];
char deviceNode[256];
uint32_t cat_ea_count;
uint32_t cat_acl_count;
uint32_t attr_ea_count;
uint32_t attr_acl_count;
PrimeBuckets CBTAttrBucket;
PrimeBuckets CBTSecurityBucket;
PrimeBuckets ABTAttrBucket;
PrimeBuckets ABTSecurityBucket;
attributeInfo lastAttrInfo;
UInt16 securityAttrName[XATTR_MAXNAMELEN];
size_t securityAttrLen;
uint32_t filelink_priv_dir_id;
uint32_t dirlink_priv_dir_id;
uint32_t dirlink_priv_dir_valence;
uint32_t calculated_dirinodes;
uint32_t calculated_dirlinks;
uint32_t journal_file_id;
uint32_t jib_file_id;
} SGlob, *SGlobPtr;
enum
{
supportsTrashVolumeCacheFeatureMask = 1,
supportsHFSPlusVolsFeatureMask = 2,
volumeIsMountedMask = 4
};
#define S_MDB 0x8000 // MDB/VHB damaged
#define S_AltMDB 0x4000 // Unused
#define S_VBM 0x2000 // volume bit map damaged
#define S_WMDB 0x1000 // wrapper MDB is damaged
#define S_OverlappingExtents 0x0800 // Overlapping extents found
#define S_BadMDBdrAlBlSt 0x0400 // Invalid drAlBlSt field in MDB
#define S_InvalidWrapperExtents 0x0200 // Invalid catalog extent start in MDB
#define S_BTH 0x8000
#define S_BTM 0x4000
#define S_Indx 0x2000 // Unused
#define S_Leaf 0x1000 // Unused
#define S_Orphan 0x0800 // orphaned file
#define S_OrphanedExtent 0x0400 // orphaned extent
#define S_ReservedNotZero 0x0200 // the flags or reserved fields are not zero
#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.
#define S_ReservedBTH 0x0080 // fields in the BTree header should be zero but are not
#define S_AttributeCount 0x0040 // incorrect number of xattr in attribute btree in comparison with attribute bit in catalog btree
#define S_SecurityCount 0x0020 // incorrect number of security xattrs in attribute btree in comparison with security bit in catalog btree
#define S_AttrRec 0x0010 // orphaned/unknown record in attribute BTree
#define S_ParentHierarchy 0x0008 // bad parent hierarchy, could not lookup parent directory record */
#define S_UnusedNodesNotZero 0x0004
#define S_IllName 0x00008000
#define S_Valence 0x00004000
#define S_FThd 0x00002000
#define S_DFCorruption 0x00001000
#define S_NoDir 0x00000800
#define S_LockedDirName 0x00000400 // locked dir name
#define S_MissingThread 0x00000200
#define S_UnlinkedFile 0x00000100
#define S_LinkCount 0x00000080
#define S_Permissions 0x00000040
#define S_FileAllocation 0x00000020
#define S_BadExtent 0x00000010
#define S_LinkErrRepair 0x00000008
#define S_LinkErrNoRepair 0x00000004
#define S_FileHardLinkChain 0x00000002
#define S_DirHardLinkChain 0x00000001
#define S_BloatedThreadRecordFound 0x8000 // 2210409, excessivly large thread record found
#define S_BadJournal 0x8000
#define S_DirtyJournal 0x4000
#define S_DamagedDir 0x8000
#define S_SymlinkCreate 0x4000
enum
{
scavInitialize = 1, scavVerify, scavRepair, scavTerminate, };
enum
{
repairLevelNoProblemsFound = 0,
repairLevelRepairIfOtherErrorsExist, repairLevelVeryMinorErrors, repairLevelVolumeRecoverable, repairLevelSomeDataLoss, repairLevelWillCauseDataLoss, repairLevelCatalogBtreeRebuild, repairLevelUnrepairable };
enum {
M_FirstMessage = 1,
M_LastMessage = 29
};
enum {
errRebuildBtree = -1001
};
enum {
kEFContigBit = 1,
kEFContigMask = 0x02,
kEFAllBit = 0,
kEFAllMask = 0x01,
kEFNoClumpBit = 2,
kEFNoClumpMask = 0x04,
kEFNoExtOvflwBit = 3,
kEFNoExtOvflwMask = 0x08,
kTFTrunExtBit = 0,
kTFTrunExtMask = 1
};
enum {
kTextEncodingMacRoman = 0L,
kTextEncodingMacFarsi = 0x8C,
kTextEncodingMacUkrainian = 0x98,
kIndexMacUkrainian = 48, kIndexMacFarsi = 49 };
#define MapEncodingToIndex(e) \
( (e) < 48 ? (e) : ( (e) == kTextEncodingMacUkrainian ? kIndexMacUkrainian : ( (e) == kTextEncodingMacFarsi ? kIndexMacFarsi : kTextEncodingMacRoman) ) )
#define MapIndexToEncoding(i) \
( (i) == kIndexMacFarsi ? kTextEncodingMacFarsi : ( (i) == kIndexMacUkrainian ? kTextEncodingMacUkrainian : (i) ) )
#define ValidMacEncoding(e) \
( ((e) < 39) || ((e) == kTextEncodingMacFarsi) || ((e) == kTextEncodingMacUkrainian) )
extern void WriteMsg( SGlobPtr GPtr, short messageID, short messageType );
extern void WriteError( SGlobPtr GPtr, short msgID, UInt32 tarID, UInt64 tarBlock );
extern short CheckPause( void );
void ScavCtrl( SGlobPtr GPtr, UInt32 ScavOp, short *ScavRes );
extern short CheckForStop( SGlobPtr GPtr );
extern OSErr RepairVolume( SGlobPtr GPtr );
extern int FixDFCorruption( const SGlobPtr GPtr, RepairOrderPtr DFOrderP );
extern OSErr ProcessFileExtents( SGlobPtr GPtr, SFCB *fcb, UInt8 forkType, UInt16 flags, Boolean isExtentsBTree, Boolean *hasOverflowExtents, UInt32 *blocksUsed );
extern OSErr GetSystemFileName(UInt32 fileID, char *filename, unsigned int *filenamelen);
extern OSErr GetFileNamePathByID(SGlobPtr GPtr, UInt32 fileID, char *fullPath, unsigned int *fullPathLen, char *fileName, unsigned int *fileNameLen, u_int16_t *status);
#define FNAME_BUF2SMALL 0x001
#define FNAME_BIGNAME 0x002
#define FPATH_BUF2SMALL 0x010
#define FPATH_BIGNAME 0x020
#define F_RESERVE_FILEID 0x100
extern int AllocBTN( SGlobPtr GPtr, short FilRefN, UInt32 NodeNum );
extern int IntError( SGlobPtr GPtr, OSErr ErrCode );
extern void RcdError( SGlobPtr GPtr, OSErr ErrCode );
extern RepairOrderPtr AllocMinorRepairOrder( SGlobPtr GPtr, size_t extraBytes );
extern int IsDuplicateRepairOrder(SGlobPtr GPtr, RepairOrderPtr orig);
extern void DeleteRepairOrder(SGlobPtr GPtr, RepairOrderPtr orig);
extern void SetDFAStage( UInt32 stage );
extern UInt32 GetDFAGlobals( void );
extern void InitializeVolumeObject( SGlobPtr GPtr );
extern void CheckEmbeddedVolInfoInMDBs( SGlobPtr GPtr );
extern VolumeObjectPtr GetVolumeObjectPtr( void );
extern OSErr GetVolumeObjectVHB( BlockDescriptor * theBlockDescPtr );
extern void GetVolumeObjectBlockNum( UInt64 * theBlockNumPtr );
extern OSErr GetVolumeObjectAlternateBlock( BlockDescriptor * theBlockDescPtr );
extern OSErr GetVolumeObjectPrimaryBlock( BlockDescriptor * theBlockDescPtr );
extern void GetVolumeObjectAlternateBlockNum( UInt64 * theBlockNumPtr );
extern void GetVolumeObjectPrimaryBlockNum( UInt64 * theBlockNumPtr );
extern OSErr GetVolumeObjectAlternateMDB( BlockDescriptor * theBlockDescPtr );
extern OSErr GetVolumeObjectPrimaryMDB( BlockDescriptor * theBlockDescPtr );
extern OSErr GetVolumeObjectVHBorMDB( BlockDescriptor * theBlockDescPtr );
extern void PrintName( int theCount, const UInt8 *theNamePtr, Boolean isUnicodeString );
extern void PrintVolumeObject( void );
extern Boolean VolumeObjectIsValid( void );
extern Boolean VolumeObjectIsHFSPlus( void );
extern Boolean VolumeObjectIsHFS( void );
extern Boolean VolumeObjectIsEmbeddedHFSPlus( void );
extern Boolean VolumeObjectIsPureHFSPlus( void );
extern Boolean VolumeObjectIsHFSX(SGlobPtr);
extern void InvalidateCalculatedVolumeBitMap( SGlobPtr GPtr );
extern OSErr GetVolumeFeatures( SGlobPtr GPtr );
OSErr FlushAlternateVolumeControlBlock( SVCB *vcb, Boolean isHFSPlus );
extern void ConvertToHFSPlusExtent(const HFSExtentRecord oldExtents, HFSPlusExtentRecord newExtents);
void add_prime_bucket_uint32(PrimeBuckets *cur, uint32_t num);
void add_prime_bucket_uint64(PrimeBuckets *cur, uint64_t num);
int compare_prime_buckets(PrimeBuckets *bucket1, PrimeBuckets *bucket2);
extern OSErr CheckCatalogBTree( SGlobPtr GPtr );
extern OSErr CheckFolderCount( SGlobPtr GPtr );
extern int RecordBadAllocation(UInt32 parID, unsigned char * filename, UInt32 forkType, UInt32 oldBlkCnt, UInt32 newBlkCnt);
extern int RecordTruncation(UInt32 parID, unsigned char * filename, UInt32 forkType, UInt64 oldSize, UInt64 newSize);
extern OSErr CatFlChk( SGlobPtr GPtr );
extern OSErr CatHChk( SGlobPtr GPtr );
extern OSErr ExtBTChk( SGlobPtr GPtr );
extern OSErr BadBlockFileExtentCheck( SGlobPtr GPtr );
extern OSErr AttrBTChk( SGlobPtr GPtr );
extern OSErr IVChk( SGlobPtr GPtr );
enum {
kCheckVolume, kMarkVolumeDirty, kMarkVolumeClean };
extern int CheckForClean( SGlobPtr GPtr, UInt8 operation, Boolean *modified );
extern int CheckIfJournaled(SGlobPtr GPtr, Boolean journal_bit_only);
extern int IsJournalEmpty(SGlobPtr);
extern OSErr VInfoChk( SGlobPtr GPtr );
extern OSErr VLockedChk( SGlobPtr GPtr );
extern void BuildExtentKey( Boolean isHFSPlus, UInt8 forkType, HFSCatalogNodeID fileNumber, UInt32 blockNumber, void * key );
extern OSErr OrphanedFileCheck( SGlobPtr GPtr, Boolean *problemsFound );
extern int cmpLongs (const void *a, const void *b);
extern int CheckAttributeRecord(SGlobPtr GPtr, const HFSPlusAttrKey *key, const HFSPlusAttrRecord *rec, UInt16 reclen);
extern void RecordXAttrBits(SGlobPtr GPtr, UInt16 flags, HFSCatalogNodeID fileid, UInt16 btreetype);
extern int FindOrigOverlapFiles(SGlobPtr GPtr);
extern void PrintOverlapFiles (SGlobPtr GPtr);
typedef int (* CheckLeafRecordProcPtr)(SGlobPtr GPtr, void *key, void *record, UInt16 recordLen);
extern int BTCheck(SGlobPtr GPtr, short refNum, CheckLeafRecordProcPtr checkLeafRecord);
extern int BTMapChk( SGlobPtr GPtr, short FilRefN );
extern OSErr ChkCName( SGlobPtr GPtr, const CatalogName *name, Boolean unicode );
extern OSErr CmpBTH( SGlobPtr GPtr, SInt16 fileRefNum );
extern int CmpBTM( SGlobPtr GPtr, short FilRefN );
extern int CmpMDB( SGlobPtr GPtr, HFSMasterDirectoryBlock * mdbP);
extern int CmpVBM( SGlobPtr GPtr );
extern OSErr CmpBlock( void *block1P, void *block2P, size_t length );
extern OSErr ChkExtRec ( SGlobPtr GPtr, const void *extents , unsigned int *lastExtentIndex);
extern int BTCheckUnusedNodes(SGlobPtr GPtr, short fileRefNum, UInt16 *btStat);
extern OSErr RebuildBTree( SGlobPtr theSGlobPtr, int FileID );
extern OSErr UpdateFolderCount( SVCB *vcb,
HFSCatalogNodeID pid,
const CatalogName *name,
SInt16 newType,
UInt32 hint,
SInt16 valenceDelta );
OSErr ZeroFileBlocks( SVCB *vcb, SFCB *fcb, UInt32 startingSector, UInt32 numberOfSectors );
OSErr MapFileBlockC (
SVCB *vcb, SFCB *fcb, UInt32 numberOfBytes, UInt64 sectorOffset, UInt64 *startSector, UInt32 *availableBytes);
OSErr DeallocateFile(SVCB *vcb, CatalogRecord * fileRec);
OSErr ExtendFileC (
SVCB *vcb, SFCB *fcb, UInt32 sectorsToAdd, UInt32 flags, UInt32 *actualSectorsAdded);
OSErr FlushExtentFile( SVCB *vcb );
void ExtDataRecToExtents(
const HFSExtentRecord oldExtents,
HFSPlusExtentRecord newExtents);
OSErr UpdateExtentRecord (
const SVCB *vcb,
SFCB *fcb,
const HFSPlusExtentKey *extentFileKey,
HFSPlusExtentRecord extentData,
UInt32 extentBTreeHint);
OSErr ReleaseExtents(
SVCB *vcb,
const HFSPlusExtentRecord extentRecord,
UInt32 *numReleasedAllocationBlocks,
Boolean *releasedLastExtent);
OSErr CheckFileExtents( SGlobPtr GPtr, UInt32 fileNumber, UInt8 forkType, const unsigned char *xattrName,
const void *extents, UInt32 *blocksUsed );
OSErr GetBTreeHeader( SGlobPtr GPtr, SFCB* fcb, BTHeaderRec *header );
OSErr CompareVolumeBitMap( SGlobPtr GPtr, SInt32 whichBuffer );
OSErr CompareVolumeHeader( SGlobPtr GPtr, HFSPlusVolumeHeader *vh );
OSErr CreateExtentsBTreeControlBlock( SGlobPtr GPtr );
OSErr CreateCatalogBTreeControlBlock( SGlobPtr GPtr );
OSErr CreateAttributesBTreeControlBlock( SGlobPtr GPtr );
OSErr CreateExtendedAllocationsFCB( SGlobPtr GPtr );
OSErr CacheWriteInPlace( SVCB *vcb, UInt32 fileRefNum, HIOParam *iopb, UInt64 currentPosition,
UInt32 maximumBytes, UInt32 *actualBytes );
OSStatus GetBlockProc (SFCB *filePtr, UInt32 blockNum, GetBlockOptions options, BlockDescriptor *block);
OSStatus ReleaseBlockProc (SFCB *filePtr, BlockDescPtr blockPtr, ReleaseBlockOptions options);
OSStatus SetEndOfForkProc (SFCB *filePtr, FSSize minEOF, FSSize maxEOF);
OSStatus SetBlockSizeProc (SFCB *filePtr, ByteCount blockSize, ItemCount minBlockCount);
void DFA_PrepareInputName(ConstStr31Param name, Boolean isHFSPlus, CatalogName *catalogName);
extern UInt32 CatalogNameSize( const CatalogName *name, Boolean isHFSPlus);
void SetupFCB( SVCB *vcb, SInt16 refNum, UInt32 fileID, UInt32 fileClumpSize );
extern void CalculateItemCount( SGlob *GPtr, UInt64 *itemCount, UInt64 *onePercent );
extern BTreeControlBlock* GetBTreeControlBlock( short refNum );
#define GetBTreeControlBlock(refNum) ((BTreeControlBlock*) ResolveFCB((refNum))->fcbBtree)
EXTERN_API_C( void )
MarkVCBDirty (SVCB * vcb);
#define MarkVCBDirty(vcb) ((void) (vcb->vcbFlags |= 0xFF00))
EXTERN_API_C( void )
MarkVCBClean (SVCB * vcb);
#define MarkVCBClean(vcb) ((void) (vcb->vcbFlags &= 0x00FF))
EXTERN_API_C( Boolean )
IsVCBDirty (SVCB * vcb);
#define IsVCBDirty(vcb) ((Boolean) ((vcb->vcbFlags & 0xFF00) != 0))
extern pascal void M_Debugger(void);
extern pascal void M_DebugStr(ConstStr255Param debuggerMsg);
#if ( DEBUG_BUILD )
#define M_Debuger() Debugger()
#define M_DebugStr( debuggerMsg ) DebugStr( debuggerMsg )
#else
#define M_Debuger()
#define M_DebugStr( debuggerMsg )
#endif
EXTERN_API_C( void )
ReturnIfError (OSErr result);
#define ReturnIfError(result) if ( (result) != noErr ) return (result); else ;
EXTERN_API_C( void )
ReturnErrorIf (Boolean condition,
OSErr result);
#define ReturnErrorIf(condition, error) if ( (condition) ) return( (error) );
EXTERN_API_C( void )
ExitOnError (OSErr result);
#define ExitOnError( result ) if ( ( result ) != noErr ) goto ErrorExit; else ;
EXTERN_API_C( UInt16 )
LongToShort (UInt32 l);
#define LongToShort( l ) l <= (UInt32)0x0000FFFF ? ((UInt16) l) : ((UInt16) 0xFFFF)
EXTERN_API_C( UInt32 )
GetDFAStage (void);
EXTERN_API_C(OSErr)
DeleteCatalogNode(SVCB *vcb, UInt32 pid, const CatalogName * name, UInt32 hint, Boolean for_rename);
EXTERN_API_C(OSErr)
GetCatalogNode(SVCB *vcb, UInt32 pid, const CatalogName * name, UInt32 hint, CatalogRecord *data);
EXTERN_API_C( SInt32 )
CompareCatalogKeys (HFSCatalogKey * searchKey,
HFSCatalogKey * trialKey);
EXTERN_API_C( SInt32 )
CompareExtendedCatalogKeys (HFSPlusCatalogKey * searchKey,
HFSPlusCatalogKey * trialKey);
EXTERN_API_C( SInt32 )
CaseSensitiveCatalogKeyCompare (HFSPlusCatalogKey * searchKey,
HFSPlusCatalogKey * trialKey);
EXTERN_API_C( SInt32 )
CompareExtentKeys (const HFSExtentKey * searchKey,
const HFSExtentKey * trialKey);
EXTERN_API_C( SInt32 )
CompareExtentKeysPlus (const HFSPlusExtentKey * searchKey,
const HFSPlusExtentKey * trialKey);
EXTERN_API_C( SInt32 )
CompareAttributeKeys (const AttributeKey * searchKey, const AttributeKey * trialKey);
EXTERN_API( SFCB* )
ResolveFCB (short fileRefNum);
EXTERN_API_C( OSErr )
ValidVolumeHeader (HFSPlusVolumeHeader * volumeHeader);
EXTERN_API_C( OSErr )
SearchBTreeRecord (SFCB *fcb,
const void * key,
UInt32 hint,
void * foundKey,
void * data,
UInt16 * dataSize,
UInt32 * newHint);
EXTERN_API_C( OSErr )
GetBTreeRecord (SFCB *fcb,
SInt16 selectionIndex,
void * key,
void * data,
UInt16 * dataSize,
UInt32 * newHint);
EXTERN_API_C( OSErr )
InsertBTreeRecord (SFCB *fcb,
const void * key,
const void * data,
UInt16 dataSize,
UInt32 * newHint);
EXTERN_API_C( OSErr )
DeleteBTreeRecord (SFCB *fcb,
const void * key);
EXTERN_API_C( OSErr )
ReplaceBTreeRecord (SFCB *fcb,
const void * key,
UInt32 hint,
void * newData,
UInt16 dataSize,
UInt32 * newHint);
EXTERN_API_C( void )
InitBTreeHeader (UInt32 fileSize,
UInt32 clumpSize,
UInt16 nodeSize,
UInt16 recordCount,
UInt16 keySize,
UInt32 attributes,
UInt32 * mapNodes,
void * buffer);
EXTERN_API_C( OSErr )
UpdateFreeCount (SVCB * vcb);
EXTERN_API_C(Boolean)
NodesAreContiguous( SFCB *fcb,
UInt32 nodeSize);
UInt32 GetTimeUTC(void);
UInt32 GetTimeLocal(Boolean forHFS);
OSErr FlushVolumeControlBlock( SVCB *vcb );
pascal short ResolveFileRefNum(SFCB * fileCtrlBlockPtr);
extern UInt32 CatalogNameLength( const CatalogName *name, Boolean isHFSPlus);
extern void CopyCatalogName( const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPLus);
extern void UpdateCatalogName( ConstStr31Param srcName, Str31 destName);
extern void BuildCatalogKey( HFSCatalogNodeID parentID, const CatalogName *name, Boolean isHFSPlus,
CatalogKey *key);
extern void UpdateVolumeEncodings( SVCB *volume, TextEncoding encoding);
OSErr BlockAllocate (SVCB *vcb, UInt32 startingBlock, UInt32 blocksRequested, UInt32 blocksMaximum,
Boolean forceContiguous, UInt32 *actualStartBlock, UInt32 *actualNumBlocks);
OSErr BlockDeallocate ( SVCB *vcb, UInt32 firstBlock, UInt32 numBlocks);
UInt32 DivideAndRoundUp( UInt32 numerator, UInt32 denominator);
OSErr BlockFindAll(SFCB *fcb, UInt32 needed);
OSErr InitializeBlockCache ( UInt32 blockSize, UInt32 blockCount );
void SetFCBSPtr( Ptr value );
Ptr GetFCBSPtr( void );
extern int utf_decodestr(const unsigned char *, size_t, u_int16_t *, size_t *, size_t);
extern int utf_encodestr(const u_int16_t *, size_t, unsigned char *, size_t *, size_t);
extern int HardLinkCheckBegin(SGlobPtr gp, void** cookie);
extern void HardLinkCheckEnd(void * cookie);
extern void CaptureHardLink(void * cookie, const HFSPlusCatalogFile *file);
extern int CheckHardLinks(void *cookie);
extern void hardlink_add_bucket(PrimeBuckets *bucket, uint32_t inode_id, uint32_t cur_link_id);
extern int inode_check(SGlobPtr, PrimeBuckets *, CatalogRecord *, CatalogKey *, Boolean);
extern void record_link_badchain(SGlobPtr, Boolean);
extern int record_link_badflags(SGlobPtr, uint32_t, Boolean, uint32_t, uint32_t);
extern int record_inode_badflags(SGlobPtr, uint32_t, Boolean, uint32_t, uint32_t, Boolean);
extern int record_dirlink_badownerflags(SGlobPtr, uint32_t, uint8_t, uint8_t, int);
extern int record_link_badfinderinfo(SGlobPtr, uint32_t, Boolean);
extern int get_first_link_id(SGlobPtr gptr, CatalogRecord *inode_rec, uint32_t inode_id, Boolean isdir, uint32_t *first_link_id);
extern int filelink_hash_inode(UInt32 inode_id, UInt32 linkCount);
extern int dirhardlink_init(SGlobPtr gptr);
extern int dirhardlink_check(SGlobPtr gptr);
extern OSErr GetCatalogRecordByID(SGlobPtr GPtr, UInt32 file_id, Boolean isHFSPlus, CatalogKey *key, CatalogRecord *rec, uint16_t *recsize);
struct HardLinkInfo;
extern int RepairHardLinkChains(SGlobPtr, Boolean);
extern int BitMapCheckBegin(SGlobPtr g);
extern int BitMapCheckEnd(void);
extern int CaptureBitmapBits(UInt32 startBit, UInt32 bitCount);
extern int ReleaseBitmapBits(UInt32 startBit, UInt32 bitCount);
extern int CheckVolumeBitMap(SGlobPtr g, Boolean repair);
extern void UpdateFreeBlockCount(SGlobPtr g);
extern int AllocateContigBitmapBits (SVCB *vcb, UInt32 numBlocks, UInt32 *actualStartBlock);
extern int IsTrimSupported(void);
extern void TrimFreeBlocks(SGlobPtr g);
struct found_blocks {
u_int64_t block;
u_int32_t fileID;
u_int32_t padding;
};
#define FOUND_BLOCKS_QUANTUM 30
extern int gBlkListEntries;
extern u_int64_t *gBlockList;
extern int gFoundBlockEntries;
extern struct found_blocks *gFoundBlocksList;
extern long gBlockSize;
void CheckPhysicalMatch(SVCB *vcb, UInt32 startblk, UInt32 blkcount, UInt32 fileNumber, UInt8 forkType);
void dumpblocklist(SGlobPtr GPtr);
#ifdef __cplusplus
};
#endif
#endif