#define SHOW_ELAPSED_TIMES 0
#if SHOW_ELAPSED_TIMES
#include <sys/time.h>
#endif
#include "Scavenger.h"
#define DisplayTimeRemaining 0
extern char __diskdev_cmds_version[];
int gGUIControl;
static void printVerifyStatus( SGlobPtr GPtr );
static Boolean IsBlueBoxSharedDrive ( DrvQElPtr dqPtr );
static int ScavSetUp( SGlobPtr GPtr );
static int ScavTerm( SGlobPtr GPtr );
int cancelProc(UInt16 progress, UInt16 secondsRemaining, Boolean progressChanged, UInt16 stage, void *context, int passno)
{
if (progressChanged) {
int base;
int pct;
int scale;
static int lastPct = -1;
if (passno < 0) {
base = 0;
scale = 100;
} else {
base = (passno * 100) / kMaxReScan; scale = 100 / kMaxReScan;
}
pct = ((progress * scale) / 100) + base;
if (pct != lastPct && pct != 100) {
fsckPrint((fsck_ctx_t)context, fsckProgress, pct);
lastPct = pct;
draw_progress(pct);
}
}
return 0;
}
int
CheckHFS( const char *rdevnode, int fsReadRef, int fsWriteRef, int checkLevel,
int repairLevel, fsck_ctx_t fsckContext, int lostAndFoundMode,
int canWrite, int *modified, int liveMode )
{
SGlob dataArea; short temp;
FileIdentifierTable *fileIdentifierTable = nil;
OSErr err = noErr;
OSErr scavError = 0;
int scanCount = 0;
int isJournaled = 0;
Boolean autoRepair;
autoRepair = (fsWriteRef != -1 && repairLevel != kNeverRepair);
if (fsckContext) {
extern fsck_message_t hfs_messages[];
extern fsck_message_t hfs_errors[];
if (fsckAddMessages(fsckContext, hfs_messages) == -1 ||
fsckAddMessages(fsckContext, hfs_errors) == -1) {
return -1;
}
}
if (__diskdev_cmds_version) {
char *vstr, *tmp = __diskdev_cmds_version;
while (*tmp && *tmp != '@')
tmp++;
if (*tmp) {
if (*tmp == '@' &&
tmp[1] == '(' &&
tmp[2] == '#' &&
tmp[3] == ')' &&
tmp[4] == ' ')
tmp += 5;
}
if (*tmp) {
vstr = strdup(tmp);
if ((tmp = vstr) != NULL) { while (*tmp && *tmp != ' ')
tmp++;
if (*tmp == ' ')
*tmp = 0; }
} else {
vstr = strdup(__diskdev_cmds_version);
}
fsckPrint(fsckContext, fsckInformation, "fsck_hfs", vstr);
free(vstr);
}
DoAgain:
ClearMemory( &dataArea, sizeof(SGlob) );
dataArea.itemsProcessed = 0; dataArea.itemsToProcess = 1;
dataArea.chkLevel = checkLevel;
dataArea.repairLevel = repairLevel;
dataArea.canWrite = canWrite;
dataArea.writeRef = fsWriteRef;
dataArea.lostAndFoundMode = lostAndFoundMode;
dataArea.DrvNum = fsReadRef;
dataArea.liveVerifyState = liveMode;
dataArea.scanCount = scanCount;
if (strlcpy(dataArea.deviceNode, rdevnode, sizeof(dataArea.deviceNode)) != strlen(rdevnode)) {
dataArea.deviceNode[0] = '\0';
}
dataArea.volumeName[ 0 ] = ' ';
dataArea.volumeName[ 1 ] = '\0';
if (fsckContext) {
dataArea.context = fsckContext;
dataArea.guiControl = true;
dataArea.userCancelProc = cancelProc;
}
ScavCtrl( &dataArea, scavInitialize, &scavError );
if ( checkLevel == kNeverCheck || (checkLevel == kDirtyCheck && dataArea.cleanUnmount) ||
scavError == R_NoMem || scavError == R_BadSig) {
goto termScav;
}
isJournaled = CheckIfJournaled( &dataArea, false );
if (isJournaled != 0 &&
scanCount == 0 &&
checkLevel != kForceCheck &&
!(checkLevel == kPartialCheck && repairLevel == kForceRepairs)) {
if (fsckGetOutputStyle(dataArea.context) == fsckOutputTraditional) {
plog("fsck_hfs: Volume is journaled. No checking performed.\n");
plog("fsck_hfs: Use the -f option to force checking.\n");
}
scavError = 0;
goto termScav;
}
dataArea.calculatedVCB->vcbDriveNumber = fsReadRef;
dataArea.calculatedVCB->vcbDriverWriteRef = fsWriteRef;
if (fsckContext) {
start_progress();
}
if ( scavError == noErr )
ScavCtrl( &dataArea, scavVerify, &scavError );
if (scavError == noErr && fsckGetVerbosity(dataArea.context) >= kDebugLog)
printVerifyStatus(&dataArea);
if (scanCount >= kMaxReScan && (dataArea.RepLevel != repairLevelNoProblemsFound)) {
fsckPrint(dataArea.context, fsckVolumeNotRepairedTries, dataArea.volumeName, scanCount);
scavError = R_RFail;
goto termScav;
}
if ( dataArea.RepLevel == repairLevelUnrepairable )
err = cdUnrepairableErr;
if ( !autoRepair &&
(dataArea.RepLevel == repairLevelVolumeRecoverable ||
dataArea.RepLevel == repairLevelCatalogBtreeRebuild ||
dataArea.RepLevel == repairLevelVeryMinorErrors) ) {
fsckPrint(dataArea.context, fsckVolumeCorruptNeedsRepair, dataArea.volumeName);
scavError = R_VFail;
goto termScav;
}
if ( scavError == noErr && dataArea.RepLevel == repairLevelNoProblemsFound ) {
if (scanCount == 0) {
fsckPrint(dataArea.context, fsckVolumeOK, dataArea.volumeName);
} else {
fsckPrint(dataArea.context, fsckRepairSuccessful, dataArea.volumeName);
}
}
if ( dataArea.RepLevel == repairLevelNoProblemsFound && repairLevel == kForceRepairs )
{
dataArea.CBTStat |= S_RebuildBTree;
dataArea.RepLevel = repairLevelCatalogBtreeRebuild;
}
if ( ((scavError == noErr) || (scavError == errRebuildBtree)) &&
(autoRepair == true) &&
(dataArea.RepLevel != repairLevelUnrepairable) &&
(dataArea.RepLevel != repairLevelNoProblemsFound) )
{
if ( dataArea.canWrite == 0 ) {
scavError = R_WrErr;
fsckPrint(dataArea.context, fsckVolumeNotRepairedInUse, dataArea.volumeName);
}
else
ScavCtrl( &dataArea, scavRepair, &scavError );
if ( scavError == noErr )
{
*modified = 1;
ScavCtrl( &dataArea, scavTerminate, &temp );
repairLevel = kMajorRepairs;
checkLevel = kAlwaysCheck;
fsckPrint(dataArea.context, fsckRecheckingVolume);
scanCount++;
goto DoAgain;
}
else {
fsckPrint(dataArea.context, fsckVolumeNotRepaired, dataArea.volumeName);
}
}
else if ( scavError != noErr ) {
fsckPrint(dataArea.context, fsckVolumeVerifyIncomplete, dataArea.volumeName);
if ( fsckGetVerbosity(dataArea.context) >= kDebugLog )
plog("\tvolume check failed with error %d \n", scavError);
}
if ( (autoRepair == true) && (dataArea.fileIdentifierTable != nil) )
{
fileIdentifierTable = (FileIdentifierTable *) AllocateMemory( GetHandleSize( (Handle) dataArea.fileIdentifierTable ) );
CopyMemory( *(dataArea.fileIdentifierTable), fileIdentifierTable, GetHandleSize( (Handle) dataArea.fileIdentifierTable ) );
}
if ( fileIdentifierTable != nil )
{
DisposeMemory( fileIdentifierTable );
}
termScav:
if (gBlkListEntries != 0)
dumpblocklist(&dataArea);
if (err == noErr) {
err = scavError;
}
if ( fsckGetVerbosity(dataArea.context) >= kDebugLog &&
(err != noErr || dataArea.RepLevel != repairLevelNoProblemsFound) )
PrintVolumeObject();
if ((fsWriteRef != -1) && (dataArea.canWrite != 0)) {
Boolean update;
if (scavError) {
CheckForClean(&dataArea, kMarkVolumeDirty, &update);
} else {
CheckForClean(&dataArea, kMarkVolumeClean, &update);
}
if (update) {
*modified = 1;
}
}
ScavCtrl( &dataArea, scavTerminate, &temp );
if (fsckContext) {
fsckPrint( fsckContext, fsckProgress, 100); draw_progress(100);
end_progress();
}
return( err );
}
void ScavCtrl( SGlobPtr GPtr, UInt32 ScavOp, short *ScavRes )
{
OSErr result;
unsigned int stat;
#if SHOW_ELAPSED_TIMES
struct timeval myStartTime;
struct timeval myEndTime;
struct timeval myElapsedTime;
struct timezone zone;
#endif
result = noErr; *ScavRes = 0;
GPtr->ScavRes = 0;
switch ( ScavOp )
{
case scavInitialize: {
Boolean modified;
int clean;
if ( ( result = ScavSetUp( GPtr ) ) ) break;
if ( IsBlueBoxSharedDrive( GPtr->DrvPtr ) )
break;
if ( ( result = CheckForStop( GPtr ) ) ) break;
clean = CheckForClean(GPtr, kCheckVolume, &modified);
if ((GPtr->chkLevel == kDirtyCheck) || (GPtr->chkLevel == kNeverCheck)) {
if (clean == 1) {
GPtr->cleanUnmount = true;
break;
}
if (GPtr->chkLevel == kNeverCheck) {
if (clean == -1)
result = R_BadSig;
else if (clean == 0) {
if (CheckIfJournaled(GPtr, false))
GPtr->cleanUnmount = true;
else
result = R_Dirty;
}
break;
}
}
if (CheckIfJournaled(GPtr, false)
&& GPtr->chkLevel != kForceCheck
&& !(GPtr->chkLevel == kPartialCheck && GPtr->repairLevel == kForceRepairs)
&& !(GPtr->chkLevel == kAlwaysCheck && GPtr->repairLevel == kMajorRepairs)) {
break;
}
if (GPtr->liveVerifyState) {
fsckPrint(GPtr->context, hfsLiveVerifyCheck);
} else if (GPtr->canWrite == 0) {
fsckPrint(GPtr->context, hfsVerifyVolWithWrite);
}
if ((GPtr->scanCount == 0) &&
(CheckIfJournaled(GPtr, true) == 1) &&
(GPtr->canWrite == 1) && (GPtr->writeRef != -1)) {
result = journal_replay(GPtr);
if (fsckGetVerbosity(GPtr->context) >= kDebugLog) {
if (result) {
plog ("\tJournal replay returned error = %d\n", result);
} else {
plog ("\tJournal replayed successfully or journal was empty\n");
}
}
}
result = IVChk( GPtr );
break;
}
case scavVerify: {
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ( BitMapCheckBegin(GPtr) != 0)
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - BitMapCheck elapsed time \n", __FUNCTION__ );
plog( "########## secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
if ( IsBlueBoxSharedDrive( GPtr->DrvPtr ) )
break;
if ( ( result = CheckForStop( GPtr ) ) )
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ( ( result = CreateExtentsBTreeControlBlock( GPtr ) ) )
break;
if ( ( result = CreateCatalogBTreeControlBlock( GPtr ) ) )
break;
if ( ( result = CreateAttributesBTreeControlBlock( GPtr ) ) )
break;
if ( ( result = CreateExtendedAllocationsFCB( GPtr ) ) )
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - create control blocks elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
CalculateItemCount( GPtr, &GPtr->itemsToProcess, &GPtr->onePercent );
GPtr->itemsProcessed += GPtr->onePercent;
if ( ( result = VLockedChk( GPtr ) ) )
break;
GPtr->itemsProcessed += GPtr->onePercent; fsckPrint(GPtr->context, hfsExtBTCheck);
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ((result = ExtBTChk(GPtr)))
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - ExtBTChk elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
if ((result = CheckForStop(GPtr)))
break;
GPtr->itemsProcessed += GPtr->onePercent;
if ((result = BadBlockFileExtentCheck(GPtr)))
break;
if ((result = CheckForStop(GPtr)))
break;
GPtr->itemsProcessed += GPtr->onePercent; GPtr->itemsProcessed += GPtr->onePercent;
fsckPrint(GPtr->context, hfsCatBTCheck);
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ( GPtr->chkLevel == kPartialCheck )
{
GPtr->CBTStat |= S_RebuildBTree;
result = errRebuildBtree;
break;
}
if ((result = CheckCatalogBTree(GPtr)))
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - CheckCatalogBTree elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
if ((result = CheckForStop(GPtr)))
break;
fsckPrint(GPtr->context, hfsCatHierCheck);
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ((result = CatHChk(GPtr)))
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - CatHChk elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
if ((result = CheckForStop(GPtr)))
break;
if (VolumeObjectIsHFSX(GPtr)) {
result = CheckFolderCount(GPtr);
if (result)
break;
if ((result=CheckForStop(GPtr)))
break;
}
if ((result = AttrBTChk(GPtr)))
break;
if ((result = CheckForStop(GPtr)))
break;
if (GPtr->VIStat & S_OverlappingExtents) {
result = FindOrigOverlapFiles(GPtr);
if (result) {
break;
}
(void) PrintOverlapFiles(GPtr);
}
result = dirhardlink_check(GPtr);
if ((result != 0) || (GPtr->CatStat & S_LinkErrNoRepair)) {
if (result == 0) {
result = -1;
}
break;
}
fsckPrint(GPtr->context, hfsVolBitmapCheck);
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ((result = CheckVolumeBitMap(GPtr, false)))
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - CheckVolumeBitMap elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
if ((result = CheckForStop(GPtr)))
break;
fsckPrint(GPtr->context, hfsVolInfoCheck);
#if SHOW_ELAPSED_TIMES
gettimeofday( &myStartTime, &zone );
#endif
if ((result = VInfoChk(GPtr)))
break;
#if SHOW_ELAPSED_TIMES
gettimeofday( &myEndTime, &zone );
timersub( &myEndTime, &myStartTime, &myElapsedTime );
plog( "\n%s - VInfoChk elapsed time \n", __FUNCTION__ );
plog( ">>>>>>>>>>>>> secs %d msecs %d \n\n",
myElapsedTime.tv_sec, myElapsedTime.tv_usec );
#endif
stat = GPtr->VIStat | GPtr->ABTStat | GPtr->EBTStat | GPtr->CBTStat |
GPtr->CatStat | GPtr->JStat;
if ( stat != 0 )
{
if ( (GPtr->RepLevel == repairLevelNoProblemsFound) || (GPtr->RepLevel == repairLevelVolumeRecoverable) )
{
unsigned int minorErrors = (GPtr->CatStat & ~S_LockedDirName) |
GPtr->VIStat | GPtr->ABTStat | GPtr->EBTStat | GPtr->CBTStat | GPtr->JStat;
if ( minorErrors == 0 )
GPtr->RepLevel = repairLevelVeryMinorErrors;
else
GPtr->RepLevel = repairLevelVolumeRecoverable;
}
}
else if ( GPtr->RepLevel == repairLevelNoProblemsFound )
{
}
GPtr->itemsProcessed = GPtr->itemsToProcess;
result = CheckForStop(GPtr); break;
}
case scavRepair: {
if ( IsBlueBoxSharedDrive( GPtr->DrvPtr ) )
break;
if ( ( result = CheckForStop(GPtr) ) )
break;
if ( GPtr->CBTStat & S_RebuildBTree ) {
fsckPrint(GPtr->context, hfsRebuildCatalogBTree);
} else {
fsckPrint(GPtr->context, fsckRepairingVolume);
}
result = RepairVolume( GPtr );
break;
}
case scavTerminate: {
result = ScavTerm(GPtr);
break;
}
}
if ( (result < 0) || (result > Max_RCode) )
{
switch ( ScavOp )
{
case scavInitialize:
case scavVerify:
if ( result == ioErr )
result = R_RdErr;
else if ( result == errRebuildBtree )
{
GPtr->RepLevel = repairLevelCatalogBtreeRebuild;
break;
}
else
result = R_VFail;
GPtr->RepLevel = repairLevelUnrepairable;
break;
case scavRepair:
result = R_RFail;
break;
default:
result = R_IntErr;
}
}
GPtr->ScavRes = result;
*ScavRes = result;
}
short CheckForStop( SGlob *GPtr )
{
OSErr err = noErr; long ticks = TickCount();
UInt16 dfaStage = (UInt16) GetDFAStage();
if ( GPtr->userCancelProc != nil )
{
UInt64 progress = 0;
Boolean progressChanged;
if ( dfaStage != kRepairStage )
{
progress = GPtr->itemsProcessed * 100;
progress /= GPtr->itemsToProcess;
progressChanged = ( progress != GPtr->lastProgress );
GPtr->lastProgress = progress;
#if( DisplayTimeRemaining )
if ( (progressChanged) && (progress > 5) )
{
elapsedTicks = TickCount() - GPtr->startTicks;
GPtr->secondsRemaining = ( ( ( 100 * elapsedTicks ) / progress ) - elapsedTicks ) / 60;
}
#endif
err = CallUserCancelProc( GPtr->userCancelProc, (UInt16)progress, (UInt16)GPtr->secondsRemaining, progressChanged, dfaStage, GPtr->context, GPtr->scanCount );
}
else
{
(void) CallUserCancelProc( GPtr->userCancelProc, (UInt16)progress, 0, false, dfaStage, GPtr->context, GPtr->scanCount );
}
}
if ( err != noErr )
err = R_UInt;
#if 0
if ( GPtr->realVCB ) if ( GPtr->realVCB->vcbWrCnt != GPtr->wrCnt )
err = R_Modified; #endif
GPtr->lastTickCount = ticks;
return ( err );
}
struct ScavStaticStructures {
SVCB vcb;
SFCB fcbList[6];
BTreeControlBlock btcb[4]; SBTPT btreePath; };
typedef struct ScavStaticStructures ScavStaticStructures;
static int ScavSetUp( SGlob *GPtr)
{
OSErr err;
SVCB * vcb;
#if !BSD
DrvQEl *drvP;
short ioRefNum;
#endif
GPtr->MinorRepairsP = nil;
GPtr->itemsProcessed = 0;
GPtr->lastProgress = 0;
GPtr->startTicks = TickCount();
{
ScavStaticStructures *pointer;
pointer = (ScavStaticStructures *) AllocateClearMemory( sizeof(ScavStaticStructures) );
if ( pointer == nil ) {
if ( fsckGetVerbosity(GPtr->context) >= kDebugLog ) {
plog( "\t error %d - could not allocate %ld bytes of memory \n",
R_NoMem, sizeof(ScavStaticStructures) );
}
return( R_NoMem );
}
GPtr->scavStaticPtr = pointer;
GPtr->DirPTPtr = AllocateClearMemory(sizeof(SDPR) * CMMaxDepth);
if ( GPtr->DirPTPtr == nil ) {
if ( fsckGetVerbosity(GPtr->context) >= kDebugLog ) {
plog( "\t error %d - could not allocate %ld bytes of memory \n",
R_NoMem, sizeof(SDPR) * CMMaxDepth );
}
return( R_NoMem );
}
GPtr->dirPathCount = CMMaxDepth;
GPtr->calculatedVCB = vcb = &pointer->vcb;
vcb->vcbGPtr = GPtr;
GPtr->FCBAPtr = (Ptr) &pointer->fcbList;
GPtr->calculatedExtentsFCB = &pointer->fcbList[0];
GPtr->calculatedCatalogFCB = &pointer->fcbList[1];
GPtr->calculatedAllocationsFCB = &pointer->fcbList[2];
GPtr->calculatedAttributesFCB = &pointer->fcbList[3];
GPtr->calculatedStartupFCB = &pointer->fcbList[4];
GPtr->calculatedRepairFCB = &pointer->fcbList[5];
GPtr->calculatedExtentsBTCB = &pointer->btcb[0];
GPtr->calculatedCatalogBTCB = &pointer->btcb[1];
GPtr->calculatedRepairBTCB = &pointer->btcb[2];
GPtr->calculatedAttributesBTCB = &pointer->btcb[3];
GPtr->BTPTPtr = (SBTPT*) &pointer->btreePath;
}
SetDFAStage( kVerifyStage );
SetFCBSPtr( GPtr->FCBAPtr );
GPtr->DrvPtr = 0;
#if !BSD
err = FindDrive( &ioRefNum, &(GPtr->DrvPtr), GPtr->DrvNum );
#endif
if ( IsBlueBoxSharedDrive( GPtr->DrvPtr ) )
return noErr;
err = GetVolumeFeatures( GPtr );
#if !BSD
if ( GPtr->DrvPtr == NULL ) return ( R_NoVol );
else
drvP = GPtr->DrvPtr;
if ( GPtr->volumeFeatures & volumeIsMountedMask )
{
FlushVol( nil, GPtr->realVCB->vcbVRefNum ); GPtr->wrCnt = GPtr->realVCB->vcbWrCnt; }
#endif
#if BSD
InitBlockCache(vcb);
vcb->vcbDriveNumber = GPtr->DrvNum;
vcb->vcbDriverReadRef = GPtr->DrvNum;
vcb->vcbDriverWriteRef = -1;
#else
vcb->vcbDriveNumber = drvP->dQDrive;
vcb->vcbDriverReadRef = drvP->dQRefNum;
vcb->vcbDriverWriteRef = drvP->dQRefNum;
vcb->vcbFSID = drvP->dQFSID;
#endif
{
SFCB *fcb;
fcb = GPtr->calculatedExtentsFCB;
fcb->fcbFileID = kHFSExtentsFileID;
fcb->fcbVolume = vcb;
fcb->fcbBtree = GPtr->calculatedExtentsBTCB;
vcb->vcbExtentsFile = fcb;
fcb = GPtr->calculatedCatalogFCB;
fcb->fcbFileID = kHFSCatalogFileID;
fcb->fcbVolume = vcb;
fcb->fcbBtree = GPtr->calculatedCatalogBTCB;
vcb->vcbCatalogFile = fcb;
fcb = GPtr->calculatedAllocationsFCB;
fcb->fcbFileID = kHFSAllocationFileID;
fcb->fcbVolume = vcb;
fcb->fcbBtree = NULL; vcb->vcbAllocationFile = fcb;
fcb = GPtr->calculatedAttributesFCB;
fcb->fcbFileID = kHFSAttributesFileID;
fcb->fcbVolume = vcb;
fcb->fcbBtree = GPtr->calculatedAttributesBTCB;
vcb->vcbAttributesFile = fcb;
fcb = GPtr->calculatedStartupFCB;
fcb->fcbFileID = kHFSStartupFileID;
fcb->fcbVolume = vcb;
fcb->fcbBtree = NULL;
vcb->vcbStartupFile = fcb;
}
{
BTreeControlBlock *btcb;
btcb = GPtr->calculatedExtentsBTCB; btcb->fcbPtr = GPtr->calculatedExtentsFCB;
btcb->getBlockProc = GetFileBlock;
btcb->releaseBlockProc = ReleaseFileBlock;
btcb->setEndOfForkProc = SetEndOfForkProc;
btcb = GPtr->calculatedCatalogBTCB; btcb->fcbPtr = GPtr->calculatedCatalogFCB;
btcb->getBlockProc = GetFileBlock;
btcb->releaseBlockProc = ReleaseFileBlock;
btcb->setEndOfForkProc = SetEndOfForkProc;
btcb = GPtr->calculatedAttributesBTCB; btcb->fcbPtr = GPtr->calculatedAttributesFCB;
btcb->getBlockProc = GetFileBlock;
btcb->releaseBlockProc = ReleaseFileBlock;
btcb->setEndOfForkProc = SetEndOfForkProc;
}
GPtr->RepLevel = repairLevelNoProblemsFound;
GPtr->ErrCode = 0;
GPtr->IntErr = noErr;
GPtr->VIStat = 0;
GPtr->ABTStat = 0;
GPtr->EBTStat = 0;
GPtr->CBTStat = 0;
GPtr->CatStat = 0;
GPtr->VeryMinorErrorsStat = 0;
GPtr->JStat = 0;
GPtr->cleanUnmount = false;
InitializeVolumeObject( GPtr );
if (VolumeObjectIsValid() == false) {
return (R_BadSig);
}
GPtr->validFilesList = (UInt32**)NewHandle( 0 );
if ( GPtr->validFilesList == nil ) {
if ( fsckGetVerbosity(GPtr->context) >= kDebugLog ) {
plog( "\t error %d - could not allocate file ID list \n", R_NoMem );
}
return( R_NoMem );
}
(void) utf_decodestr((unsigned char *)KAUTH_FILESEC_XATTR, strlen(KAUTH_FILESEC_XATTR), GPtr->securityAttrName, &GPtr->securityAttrLen, sizeof(GPtr->securityAttrName));
return( noErr );
}
static int ScavTerm( SGlobPtr GPtr )
{
SFCB *fcbP;
BTreeControlBlock *btcbP;
RepairOrderPtr rP;
OSErr err;
ExtentsTable **extentsTableH;
ExtentInfo *curExtentInfo;
int i;
(void) BitMapCheckEnd();
while( (rP = GPtr->MinorRepairsP) != nil ) {
GPtr->MinorRepairsP = rP->link; DisposeMemory(rP);
err = MemError();
}
if( GPtr->validFilesList != nil )
DisposeHandle( (Handle) GPtr->validFilesList );
if( GPtr->overlappedExtents != nil ) {
extentsTableH = GPtr->overlappedExtents;
for (i=0; i<(**extentsTableH).count; i++) {
curExtentInfo = &((**extentsTableH).extentInfo[i]);
if (curExtentInfo->attrname) {
free(curExtentInfo->attrname);
}
}
DisposeHandle( (Handle) GPtr->overlappedExtents );
}
if( GPtr->fileIdentifierTable != nil )
DisposeHandle( (Handle) GPtr->fileIdentifierTable );
if( GPtr->calculatedVCB == nil ) return( noErr );
fcbP = GPtr->calculatedExtentsFCB; if ( fcbP != nil )
{
btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
if ( btcbP != nil)
{
if( btcbP->refCon != nil )
{
if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
{
DisposeMemory(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr);
err = MemError();
}
DisposeMemory( (Ptr)btcbP->refCon );
err = MemError();
btcbP->refCon = nil;
}
fcbP = GPtr->calculatedCatalogFCB; btcbP = (BTreeControlBlock*)fcbP->fcbBtree;
if( btcbP->refCon != nil )
{
if(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr != nil)
{
DisposeMemory(((BTreeExtensionsRec*)btcbP->refCon)->BTCBMPtr);
err = MemError();
}
DisposeMemory( (Ptr)btcbP->refCon );
err = MemError();
btcbP->refCon = nil;
}
}
}
DisposeMemory(GPtr->DirPTPtr);
DisposeMemory((ScavStaticStructures *)GPtr->scavStaticPtr);
GPtr->scavStaticPtr = nil;
GPtr->calculatedVCB = nil;
return( noErr );
}
#define BLUE_BOX_SHARED_DRVR_NAME "\p.BlueBoxShared"
#define BLUE_BOX_FLOPPY_WHERE_STRING "\pdisk%d (Shared)"
#define SONY_DRVR_NAME "\p.Sony"
struct IconAndStringRec {
char icon[ 256 ];
Str255 string;
};
typedef struct IconAndStringRec IconAndStringRec, * IconAndStringRecPtr;
Boolean IsBlueBoxSharedDrive ( DrvQElPtr dqPtr )
{
#if 0
Str255 blueBoxSharedDriverName = BLUE_BOX_SHARED_DRVR_NAME;
Str255 blueBoxFloppyWhereString = BLUE_BOX_FLOPPY_WHERE_STRING;
Str255 sonyDriverName = SONY_DRVR_NAME;
DCtlHandle driverDCtlHandle;
DCtlPtr driverDCtlPtr;
DRVRHeaderPtr drvrHeaderPtr;
StringPtr driverName;
if ( dqPtr == NULL )
return false;
driverDCtlHandle = GetDCtlEntry(dqPtr->dQRefNum);
driverDCtlPtr = *driverDCtlHandle;
if((((driverDCtlPtr->dCtlFlags) & Is_Native_Mask) == 0) && (driverDCtlPtr->dCtlDriver != nil))
{
if (((driverDCtlPtr->dCtlFlags) & Is_Ram_Based_Mask) == 0)
{
drvrHeaderPtr = (DRVRHeaderPtr)driverDCtlPtr->dCtlDriver;
}
else
{
HLock((Handle)(driverDCtlPtr)->dCtlDriver);
drvrHeaderPtr = (DRVRHeaderPtr)*((Handle)(driverDCtlPtr->dCtlDriver));
}
driverName = (StringPtr)&(drvrHeaderPtr->drvrName);
if (!(IdenticalString(driverName,blueBoxSharedDriverName,nil)))
{
return( true );
}
if (!(IdenticalString(driverName,sonyDriverName,nil)))
{
CntrlParam paramBlock;
paramBlock.ioCompletion = nil;
paramBlock.ioNamePtr = nil;
paramBlock.ioVRefNum = dqPtr->dQDrive;
paramBlock.ioCRefNum = dqPtr->dQRefNum;
paramBlock.csCode = kDriveIcon;
if ( noErr == PBControlSync( (ParmBlkPtr) ¶mBlock ) )
{
IconAndStringRecPtr iconAndStringRecPtr;
StringPtr whereStringPtr;
iconAndStringRecPtr = * (IconAndStringRecPtr*) & paramBlock.csParam;
whereStringPtr = (StringPtr) & iconAndStringRecPtr->string;
if (!(IdenticalString(whereStringPtr,blueBoxFloppyWhereString,nil)))
{
return( true );
}
}
}
}
#endif
return false;
}
static
void printVerifyStatus(SGlobPtr GPtr)
{
UInt32 stat;
stat = GPtr->VIStat | GPtr->ABTStat | GPtr->EBTStat | GPtr->CBTStat | GPtr->CatStat;
if ( stat != 0 ) {
plog(" Verify Status: VIStat = 0x%04x, ABTStat = 0x%04x EBTStat = 0x%04x\n",
GPtr->VIStat, GPtr->ABTStat, GPtr->EBTStat);
plog(" CBTStat = 0x%04x CatStat = 0x%08x\n",
GPtr->CBTStat, GPtr->CatStat);
}
}