#include "DAStage.h"
#include "DABase.h"
#include "DACallback.h"
#include "DADialog.h"
#include "DADisk.h"
#include "DAFileSystem.h"
#include "DALog.h"
#include "DAMain.h"
#include "DAMount.h"
#include "DAPrivate.h"
#include "DAQueue.h"
#include "DASupport.h"
#include <fsproperties.h>
#include <unistd.h>
#include <sys/loadable_fs.h>
#include <sys/mount.h>
#include <IOKit/storage/IOMedia.h>
static CFRunLoopSourceRef __gDAStageRunLoopSource = NULL;
static void __DAStageAppeared( DADiskRef disk );
static void __DAStageMount( DADiskRef disk );
static void __DAStageMountCallback( int status, CFURLRef mountpoint, void * context );
static void __DAStageMountApproval( DADiskRef disk );
static void __DAStageMountApprovalCallback( CFTypeRef response, void * context );
static void __DAStageMountAuthorization( DADiskRef disk );
static void __DAStageMountAuthorizationCallback( DAReturn status, void * context );
static void __DAStagePeek( DADiskRef disk );
static void __DAStagePeekCallback( CFTypeRef response, void * context );
static CFComparisonResult __DAStagePeekCompare( const void * value1, const void * value2, void * context );
static void __DAStageProbe( DADiskRef disk );
static void __DAStageProbeCallback( int status, CFBooleanRef clean, CFStringRef name, CFUUIDRef uuid, void * context );
static void __DAStageRepair( DADiskRef disk );
static void __DAStageRepairCallback( int status, void * context );
static void __DAStageAppeared( DADiskRef disk )
{
DADiskSetState( disk, kDADiskStateStagedAppear, TRUE );
DADiskAppearedCallback( disk );
DAStageSignal( );
}
static void __DAStageDispatch( void * info )
{
static Boolean fresh = FALSE;
CFIndex count;
CFIndex index;
Boolean quiet = TRUE;
count = CFArrayGetCount( gDADiskList );
for ( index = 0; index < count; index++ )
{
DADiskRef disk;
disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index );
if ( DADiskGetState( disk, kDADiskStateCommandActive ) == FALSE )
{
if ( DADiskGetState( disk, kDADiskStateStagedProbe ) == FALSE )
{
if ( fresh )
{
DAFileSystemListRefresh( );
DAMountMapListRefresh1( );
DAMountMapListRefresh2( );
fresh = FALSE;
}
__DAStageProbe( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedPeek ) == FALSE )
{
__DAStagePeek( disk );
}
else if ( DADiskGetState( disk, kDADiskStateRequireRepair ) == FALSE )
{
if ( DADiskGetState( disk, kDADiskStateStagedRepair ) == FALSE )
{
__DAStageRepair( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedApprove ) == FALSE )
{
__DAStageMountApproval( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedAuthorize ) == FALSE )
{
__DAStageMountAuthorization( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedMount ) == FALSE )
{
__DAStageMount( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedAppear ) == FALSE )
{
__DAStageAppeared( disk );
}
else
{
if ( gDAConsoleUserList == NULL )
{
if ( DADiskGetDescription( disk, kDADiskDescriptionMediaTypeKey ) )
{
if ( DAUnitGetState( disk, kDAUnitStateStagedUnreadable ) == FALSE )
{
if ( _DAUnitIsUnreadable( disk ) )
{
DADiskEject( disk, kDADiskEjectOptionDefault, NULL );
}
DAUnitSetState( disk, kDAUnitStateStagedUnreadable, TRUE );
}
}
}
continue;
}
}
else if ( DADiskGetState( disk, kDADiskStateStagedAppear ) == FALSE )
{
if ( DADiskGetState( disk, kDADiskStateRequireRepair ) )
{
CFIndex subcount;
CFIndex subindex;
subcount = CFArrayGetCount( gDADiskList );
for ( subindex = 0; subindex < subcount; subindex++ )
{
DADiskRef subdisk;
subdisk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, subindex );
if ( DADiskGetBSDUnit( disk ) == DADiskGetBSDUnit( subdisk ) )
{
if ( DADiskGetState( subdisk, kDADiskStateStagedProbe ) == FALSE )
{
break;
}
if ( DADiskGetState( subdisk, kDADiskStateStagedAppear ) == FALSE )
{
if ( DADiskGetState( subdisk, kDADiskStateRequireRepair ) == FALSE )
{
break;
}
}
}
}
if ( subindex == subcount )
{
__DAStageAppeared( disk );
__DAStageRepair( disk );
}
}
else
__DAStageAppeared( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedRepair ) == FALSE )
{
if ( DADiskGetState( disk, kDADiskStateRequireRepair ) )
{
CFIndex subcount;
CFIndex subindex;
subcount = CFArrayGetCount( gDADiskList );
for ( subindex = 0; subindex < subcount; subindex++ )
{
DADiskRef subdisk;
subdisk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, subindex );
if ( DADiskGetBSDUnit( disk ) == DADiskGetBSDUnit( subdisk ) )
{
if ( DADiskGetState( subdisk, kDADiskStateStagedProbe ) == FALSE )
{
break;
}
if ( DADiskGetState( subdisk, kDADiskStateStagedMount ) == FALSE )
{
if ( DADiskGetState( subdisk, kDADiskStateRequireRepair ) == FALSE )
{
break;
}
}
}
}
if ( subindex == subcount )
{
if ( gDAExit )
{
continue;
}
__DAStageRepair( disk );
}
}
else
{
__DAStageRepair( disk );
}
}
else if ( DADiskGetState( disk, kDADiskStateStagedApprove ) == FALSE )
{
__DAStageMountApproval( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedAuthorize ) == FALSE )
{
__DAStageMountAuthorization( disk );
}
else if ( DADiskGetState( disk, kDADiskStateStagedMount ) == FALSE )
{
__DAStageMount( disk );
}
else
{
continue;
}
}
quiet = FALSE;
}
count = CFArrayGetCount( gDARequestList );
if ( count )
{
CFMutableSetRef dependencies;
dependencies = CFSetCreateMutable( kCFAllocatorDefault, 0, &kCFTypeSetCallBacks );
if ( dependencies )
{
for ( index = 0; index < count; index++ )
{
DARequestRef request;
request = ( void * ) CFArrayGetValueAtIndex( gDARequestList, index );
if ( request )
{
DADiskRef disk;
Boolean dispatch = TRUE;
disk = DARequestGetDisk( request );
if ( disk )
{
CFArrayRef link;
link = DARequestGetLink( request );
if ( link )
{
CFIndex subcount;
CFIndex subindex;
subcount = CFArrayGetCount( link );
for ( subindex = 0; subindex < subcount; subindex++ )
{
DARequestRef subrequest;
subrequest = ( void * ) CFArrayGetValueAtIndex( link, subindex );
if ( CFSetContainsValue( dependencies, DARequestGetDisk( subrequest ) ) )
{
break;
}
}
if ( subindex < subcount )
{
dispatch = FALSE;
}
}
if ( CFSetContainsValue( dependencies, disk ) )
{
dispatch = FALSE;
}
}
else
{
if ( index )
{
break;
}
}
if ( dispatch )
{
if ( DARequestGetKind( request ) == _kDADiskMount )
{
if ( fresh )
{
DAFileSystemListRefresh( );
DAMountMapListRefresh1( );
DAMountMapListRefresh2( );
fresh = FALSE;
}
}
dispatch = DARequestDispatch( request );
}
if ( dispatch )
{
CFArrayRemoveValueAtIndex( gDARequestList, index );
count--;
index--;
}
else
{
if ( disk )
{
CFArrayRef link;
link = DARequestGetLink( request );
if ( link )
{
CFIndex subcount;
CFIndex subindex;
subcount = CFArrayGetCount( link );
for ( subindex = 0; subindex < subcount; subindex++ )
{
DARequestRef subrequest;
subrequest = ( void * ) CFArrayGetValueAtIndex( link, subindex );
CFSetSetValue( dependencies, DARequestGetDisk( subrequest ) );
}
}
CFSetSetValue( dependencies, disk );
}
}
}
}
CFRelease( dependencies );
}
quiet = FALSE;
}
if ( quiet )
{
fresh = TRUE;
gDAIdle = TRUE;
DAIdleCallback( );
___vproc_transaction_end( );
if ( gDAConsoleUser )
{
count = CFArrayGetCount( gDADiskList );
for ( index = 0; index < count; index++ )
{
DADiskRef disk;
disk = ( void * ) CFArrayGetValueAtIndex( gDADiskList, index );
if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWholeKey ) == kCFBooleanTrue )
{
if ( DAUnitGetState( disk, kDAUnitStateStagedUnreadable ) == FALSE )
{
if ( _DAUnitIsUnreadable( disk ) )
{
DADialogShowDeviceUnreadable( disk );
}
DAUnitSetState( disk, kDAUnitStateStagedUnreadable, TRUE );
}
}
if ( DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey ) )
{
if ( DADiskGetState( disk, kDADiskStateStagedUnrepairable ) == FALSE )
{
if ( DADiskGetState( disk, kDADiskStateRequireRepair ) )
{
if ( DADiskGetOption( disk, kDADiskOptionMountAutomatic ) )
{
if ( DADiskGetClaim( disk ) == NULL )
{
DADialogShowDeviceUnrepairable( disk );
}
}
}
DADiskSetState( disk, kDADiskStateStagedUnrepairable, TRUE );
}
}
}
}
}
}
static void __DAStageMount( DADiskRef disk )
{
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( DAUnitGetState( disk, kDAUnitStateCommandActive ) == FALSE )
{
CFRetain( disk );
DADiskSetState( disk, kDADiskStateStagedMount, TRUE );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
DAUnitSetState( disk, kDAUnitStateCommandActive, TRUE );
DALogDebug( " mounted disk, id = %@, ongoing.", disk );
DAMountWithArguments( disk, NULL, __DAStageMountCallback, disk, CFSTR( "automatic" ), NULL );
}
}
static void __DAStageMountCallback( int status, CFURLRef mountpoint, void * context )
{
DADiskRef disk = context;
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( status )
{
if ( status == ECANCELED )
{
DALogDebug( " mounted disk, id = %@, deferred.", disk );
}
else
{
DALogDebug( " mounted disk, id = %@, failure.", disk );
DALogError( "unable to mount %@ (status code 0x%08X).", disk, status );
}
}
else
{
DADiskSetBypath( disk, mountpoint );
DADiskSetDescription( disk, kDADiskDescriptionVolumePathKey, mountpoint );
DALogDebug( " mounted disk, id = %@, success.", disk );
if ( DADiskGetState( disk, kDADiskStateStagedAppear ) )
{
DADiskDescriptionChangedCallback( disk, kDADiskDescriptionVolumePathKey );
}
}
DAUnitSetState( disk, kDAUnitStateCommandActive, FALSE );
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DAStageSignal( );
CFRelease( disk );
}
static void __DAStageMountApproval( DADiskRef disk )
{
Boolean mount = TRUE;
if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanFalse )
{
mount = FALSE;
}
if ( DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey ) )
{
mount = FALSE;
}
DADiskSetState( disk, kDADiskStateStagedApprove, TRUE );
if ( mount )
{
CFRetain( disk );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
DADiskMountApprovalCallback( disk, __DAStageMountApprovalCallback, disk );
}
else
{
DADiskSetState( disk, kDADiskStateStagedMount, TRUE );
DAStageSignal( );
}
}
static void __DAStageMountApprovalCallback( CFTypeRef response, void * context )
{
DADiskRef disk = context;
DADissenterRef dissenter = response;
if ( dissenter )
{
if ( DADissenterGetStatus( dissenter ) == 0xF8DAFF01 )
{
DADiskSetState( disk, _kDADiskStateRequireAuthorize, TRUE );
}
else if ( DADissenterGetStatus( dissenter ) == 0xF8DAFF02 )
{
DADiskSetState( disk, _kDADiskStateMountPreferenceNoWrite, TRUE );
}
else if ( DADissenterGetStatus( dissenter ) == 0xF8DAFF03 )
{
DADiskSetState( disk, _kDADiskStateRequireAuthorize, TRUE );
DADiskSetState( disk, _kDADiskStateMountPreferenceNoWrite, TRUE );
}
else
DADiskSetState( disk, kDADiskStateStagedMount, TRUE );
}
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DAStageSignal( );
CFRelease( disk );
}
static void __DAStageMountAuthorization( DADiskRef disk )
{
DADiskSetState( disk, kDADiskStateStagedAuthorize, TRUE );
if ( DADiskGetState( disk, _kDADiskStateRequireAuthorize ) )
{
CFRetain( disk );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
DAAuthorizeWithCallback( NULL,
_kDAAuthorizeOptionAuthenticateAdministrator,
disk,
___UID_ROOT,
___GID_WHEEL,
__DAStageMountAuthorizationCallback,
disk,
_kDAAuthorizeRightMount );
}
else
{
DAStageSignal( );
}
}
static void __DAStageMountAuthorizationCallback( DAReturn status, void * context )
{
DADiskRef disk = context;
if ( status )
{
DADiskSetState( disk, kDADiskStateStagedMount, TRUE );
}
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DAStageSignal( );
CFRelease( disk );
}
static void __DAStagePeek( DADiskRef disk )
{
CFMutableArrayRef candidates;
candidates = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if ( candidates )
{
DASessionRef session;
CFArrayRef sessionList;
CFIndex sessionListCount;
CFIndex sessionListIndex;
sessionList = gDASessionList;
sessionListCount = CFArrayGetCount( sessionList );
for ( sessionListIndex = 0; sessionListIndex < sessionListCount; sessionListIndex++ )
{
DACallbackRef callback;
CFArrayRef callbackList;
CFIndex callbackListCount;
CFIndex callbackListIndex;
session = ( void * ) CFArrayGetValueAtIndex( sessionList, sessionListIndex );
callbackList = DASessionGetCallbackRegister( session );
callbackListCount = CFArrayGetCount( callbackList );
for ( callbackListIndex = 0; callbackListIndex < callbackListCount; callbackListIndex++ )
{
callback = ( void * ) CFArrayGetValueAtIndex( callbackList, callbackListIndex );
if ( DACallbackGetKind( callback ) == _kDADiskPeekCallback )
{
CFArrayAppendValue( candidates, callback );
}
}
}
CFArraySortValues( candidates, CFRangeMake( 0, CFArrayGetCount( candidates ) ), __DAStagePeekCompare, NULL );
CFRetain( disk );
DADiskSetContext( disk, candidates );
DADiskSetState( disk, kDADiskStateStagedPeek, TRUE );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
__DAStagePeekCallback( NULL, disk );
CFRelease( candidates );
}
}
static void __DAStagePeekCallback( CFTypeRef response, void * context )
{
CFMutableArrayRef candidates;
DADiskRef disk = context;
candidates = ( void * ) DADiskGetContext( disk );
if ( CFArrayGetCount( candidates ) )
{
DACallbackRef candidate;
candidate = ( void * ) CFArrayGetValueAtIndex( candidates, 0 );
CFRetain( candidate );
CFArrayRemoveValueAtIndex( candidates, 0 );
DADiskPeekCallback( disk, candidate, __DAStagePeekCallback, context );
CFRelease( candidate );
return;
}
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DADiskSetContext( disk, NULL );
DAStageSignal( );
CFRelease( disk );
}
static CFComparisonResult __DAStagePeekCompare( const void * value1, const void * value2, void * context )
{
SInt32 order1 = DACallbackGetOrder( ( void * ) value1 );
SInt32 order2 = DACallbackGetOrder( ( void * ) value2 );
if ( order1 > order2 ) return kCFCompareGreaterThan;
if ( order1 < order2 ) return kCFCompareLessThan;
return kCFCompareEqualTo;
}
static void __DAStageProbe( DADiskRef disk )
{
if ( DAUnitGetState( disk, kDAUnitStateCommandActive ) == FALSE )
{
CFMutableArrayRef candidates;
candidates = CFArrayCreateMutableCopy( kCFAllocatorDefault, 0, gDAFileSystemProbeList );
if ( candidates )
{
CFNumberRef size;
size = DADiskGetDescription( disk, kDADiskDescriptionMediaSizeKey );
if ( size )
{
if ( ___CFNumberGetIntegerValue( size ) == 0 )
{
CFArrayRemoveAllValues( candidates );
}
}
CFRetain( disk );
DADiskSetFileSystem( disk, NULL );
DADiskSetContext( disk, candidates );
DADiskSetState( disk, kDADiskStateStagedProbe, TRUE );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
DAUnitSetState( disk, kDAUnitStateCommandActive, TRUE );
__DAStageProbeCallback( -1, NULL, NULL, NULL, disk );
CFRelease( candidates );
}
}
}
static void __DAStageProbeCallback( int status, CFBooleanRef clean, CFStringRef name, CFUUIDRef uuid, void * context )
{
DADiskRef disk = context;
CFMutableArrayRef keys = NULL;
CFStringRef kind = NULL;
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( status )
{
CFMutableArrayRef candidates;
candidates = ( void * ) DADiskGetContext( disk );
if ( DADiskGetFileSystem( disk ) )
{
kind = DAFileSystemGetKind( DADiskGetFileSystem( disk ) );
DALogDebug( " probed disk, id = %@, with %@, failure.", disk, kind );
if ( status != FSUR_UNRECOGNIZED )
{
DALogError( "unable to probe %@ (status code 0x%08X).", disk, status );
}
}
while ( CFArrayGetCount( candidates ) )
{
CFDictionaryRef candidate;
candidate = CFArrayGetValueAtIndex( candidates, 0 );
if ( candidate )
{
DAFileSystemRef filesystem;
filesystem = ( void * ) CFDictionaryGetValue( candidate, kDAFileSystemKey );
if ( filesystem )
{
CFDictionaryRef properties;
properties = CFDictionaryGetValue( candidate, CFSTR( kFSMediaPropertiesKey ) );
if ( properties )
{
boolean_t match = FALSE;
IOServiceMatchPropertyTable( DADiskGetIOMedia( disk ), properties, &match );
if ( match )
{
kind = DAFileSystemGetKind( filesystem );
DADiskSetFileSystem( disk, filesystem );
if ( CFDictionaryGetValue( candidate, CFSTR( "autodiskmount" ) ) == kCFBooleanFalse )
{
DADiskSetOption( disk, kDADiskOptionMountAutomatic, FALSE );
DADiskSetOption( disk, kDADiskOptionMountAutomaticNoDefer, FALSE );
}
CFArrayRemoveValueAtIndex( candidates, 0 );
DALogDebug( " probed disk, id = %@, with %@, ongoing.", disk, kind );
DAFileSystemProbe( filesystem, DADiskGetDevice( disk ), __DAStageProbeCallback, context );
return;
}
}
}
}
CFArrayRemoveValueAtIndex( candidates, 0 );
}
}
DADiskSetState( disk, kDADiskStateRequireRepair, FALSE );
DADiskSetState( disk, kDADiskStateRequireRepairQuotas, FALSE );
if ( status )
{
kind = NULL;
if ( DADiskGetFileSystem( disk ) )
{
DADiskSetFileSystem( disk, NULL );
DALogDebug( " probed disk, id = %@, no match.", disk );
}
}
else
{
kind = DAFileSystemGetKind( DADiskGetFileSystem( disk ) );
if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse )
{
clean = kCFBooleanTrue;
}
if ( clean == kCFBooleanFalse )
{
DADiskSetState( disk, kDADiskStateRequireRepair, TRUE );
DADiskSetState( disk, kDADiskStateRequireRepairQuotas, TRUE );
}
DALogDebug( " probed disk, id = %@, with %@, success.", disk, kind );
}
keys = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
if ( keys )
{
CFTypeRef object;
object = IORegistryEntryCreateCFProperty( DADiskGetIOMedia( disk ), CFSTR( kIOMediaWritableKey ), kCFAllocatorDefault, 0 );
if ( object )
{
if ( DADiskCompareDescription( disk, kDADiskDescriptionMediaWritableKey, object ) )
{
DADiskSetDescription( disk, kDADiskDescriptionMediaWritableKey, object );
CFArrayAppendValue( keys, kDADiskDescriptionMediaWritableKey );
}
CFRelease( object );
}
object = kind ? kCFBooleanTrue : kCFBooleanFalse;
if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeMountableKey, object ) )
{
DADiskSetDescription( disk, kDADiskDescriptionVolumeMountableKey, object );
CFArrayAppendValue( keys, kDADiskDescriptionVolumeMountableKey );
}
if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeKindKey, kind ) )
{
DADiskSetDescription( disk, kDADiskDescriptionVolumeKindKey, kind );
CFArrayAppendValue( keys, kDADiskDescriptionVolumeKindKey );
}
if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeNameKey, name ) )
{
DADiskSetDescription( disk, kDADiskDescriptionVolumeNameKey, name );
CFArrayAppendValue( keys, kDADiskDescriptionVolumeNameKey );
}
if ( DADiskCompareDescription( disk, kDADiskDescriptionVolumeUUIDKey, uuid ) )
{
DADiskSetDescription( disk, kDADiskDescriptionVolumeUUIDKey, uuid );
CFArrayAppendValue( keys, kDADiskDescriptionVolumeUUIDKey );
}
if ( CFArrayGetCount( keys ) )
{
if ( DADiskGetState( disk, kDADiskStateStagedAppear ) )
{
DADiskDescriptionChangedCallback( disk, keys );
}
}
CFRelease( keys );
}
if ( DADiskGetState( disk, kDADiskStateStagedMount ) == FALSE )
{
struct statfs * mountList;
int mountListCount;
int mountListIndex;
mountListCount = getmntinfo( &mountList, MNT_NOWAIT );
for ( mountListIndex = 0; mountListIndex < mountListCount; mountListIndex++ )
{
if ( mountList[mountListIndex].f_fsid.val[0] == DADiskGetBSDNode( disk ) )
{
CFURLRef path;
path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault,
( void * ) mountList[mountListIndex].f_mntonname,
strlen( mountList[mountListIndex].f_mntonname ),
TRUE );
if ( path )
{
_DAMountCreateTrashFolder( disk, path );
DADiskSetBypath( disk, path );
DADiskSetDescription( disk, kDADiskDescriptionVolumePathKey, path );
CFRelease( path );
}
if ( strcmp( mountList[mountListIndex].f_mntonname, "/" ) == 0 )
{
path = DAMountCreateMountPointWithAction( disk, kDAMountPointActionLink );
if ( path )
{
DADiskSetBypath( disk, path );
CFRelease( path );
}
DADiskSetOption( disk, kDADiskOptionMountAutomatic, TRUE );
DADiskSetOption( disk, kDADiskOptionMountAutomaticNoDefer, TRUE );
}
DADiskSetState( disk, kDADiskStateRequireRepair, FALSE );
DADiskSetState( disk, kDADiskStateRequireRepairQuotas, FALSE );
break;
}
}
}
DAUnitSetState( disk, kDAUnitStateCommandActive, FALSE );
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DADiskSetContext( disk, NULL );
DAStageSignal( );
CFRelease( disk );
}
static void __DAStageRepair( DADiskRef disk )
{
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( DAUnitGetState( disk, kDAUnitStateCommandActive ) == FALSE )
{
DADiskSetState( disk, kDADiskStateStagedRepair, TRUE );
if ( DADiskGetState( disk, kDADiskStateRequireRepair ) )
{
CFRetain( disk );
DADiskSetState( disk, kDADiskStateCommandActive, TRUE );
DAUnitSetState( disk, kDAUnitStateCommandActive, TRUE );
DALogDebug( " repaired disk, id = %@, ongoing.", disk );
DAFileSystemRepair( DADiskGetFileSystem( disk ), DADiskGetDevice( disk ), __DAStageRepairCallback, disk );
}
else
{
DAStageSignal( );
}
}
}
static void __DAStageRepairCallback( int status, void * context )
{
DADiskRef disk = context;
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( status )
{
DALogDebug( " repaired disk, id = %@, failure.", disk );
DALogError( "unable to repair %@ (status code 0x%08X).", disk, status );
}
else
{
DADiskSetState( disk, kDADiskStateRequireRepair, FALSE );
DALogDebug( " repaired disk, id = %@, success.", disk );
}
DAUnitSetState( disk, kDAUnitStateCommandActive, FALSE );
DADiskSetState( disk, kDADiskStateCommandActive, FALSE );
DAStageSignal( );
CFRelease( disk );
}
CFRunLoopSourceRef DAStageCreateRunLoopSource( CFAllocatorRef allocator, CFIndex order )
{
if ( __gDAStageRunLoopSource == NULL )
{
CFRunLoopSourceContext context = { 0 };
context.perform = __DAStageDispatch;
__gDAStageRunLoopSource = CFRunLoopSourceCreate( allocator, order, &context );
}
if ( __gDAStageRunLoopSource )
{
CFRetain( __gDAStageRunLoopSource );
}
return __gDAStageRunLoopSource;
}
void DAStageSignal( void )
{
if ( gDAIdle )
{
___vproc_transaction_begin( );
}
gDAIdle = FALSE;
CFRunLoopSourceSignal( __gDAStageRunLoopSource );
}