#include "DAProbe.h"
#include "DALog.h"
#include "DAMain.h"
#include "DASupport.h"
#include <fsproperties.h>
#include <sys/loadable_fs.h>
struct __DAProbeCallbackContext
{
DAProbeCallback callback;
void * callbackContext;
CFMutableArrayRef candidates;
DADiskRef disk;
DAFileSystemRef filesystem;
};
typedef struct __DAProbeCallbackContext __DAProbeCallbackContext;
static void __DAProbeCallback( int status, CFBooleanRef clean, CFStringRef name, CFStringRef type, CFUUIDRef uuid, void * parameter )
{
__DAProbeCallbackContext * context = parameter;
DALogDebugHeader( "%s -> %s", gDAProcessNameID, gDAProcessNameID );
if ( status )
{
if ( context->filesystem )
{
CFStringRef kind;
kind = DAFileSystemGetKind( context->filesystem );
DALogDebug( " probed disk, id = %@, with %@, failure.", context->disk, kind );
if ( status != FSUR_UNRECOGNIZED )
{
DALogError( "unable to probe %@ (status code 0x%08X).", context->disk, status );
}
CFRelease( context->filesystem );
context->filesystem = NULL;
}
while ( CFArrayGetCount( context->candidates ) )
{
CFDictionaryRef candidate;
candidate = CFArrayGetValueAtIndex( context->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( context->disk ), properties, &match );
if ( match )
{
CFStringRef kind;
kind = DAFileSystemGetKind( filesystem );
CFRetain( filesystem );
context->filesystem = filesystem;
if ( CFDictionaryGetValue( candidate, CFSTR( "autodiskmount" ) ) == kCFBooleanFalse )
{
DADiskSetState( context->disk, _kDADiskStateMountAutomatic, FALSE );
DADiskSetState( context->disk, _kDADiskStateMountAutomaticNoDefer, FALSE );
}
CFArrayRemoveValueAtIndex( context->candidates, 0 );
DALogDebug( " probed disk, id = %@, with %@, ongoing.", context->disk, kind );
DAFileSystemProbe( filesystem, DADiskGetDevice( context->disk ), __DAProbeCallback, context );
return;
}
}
}
}
CFArrayRemoveValueAtIndex( context->candidates, 0 );
}
}
else
{
CFStringRef kind;
kind = DAFileSystemGetKind( context->filesystem );
DALogDebug( " probed disk, id = %@, with %@, success.", context->disk, kind );
}
if ( context->callback )
{
( context->callback )( status, context->filesystem, clean, name, type, uuid, context->callbackContext );
}
CFRelease( context->candidates );
CFRelease( context->disk );
if ( context->filesystem ) CFRelease( context->filesystem );
free( context );
}
void DAProbe( DADiskRef disk, DAProbeCallback callback, void * callbackContext )
{
CFMutableArrayRef candidates = NULL;
__DAProbeCallbackContext * context = NULL;
CFNumberRef size = NULL;
int status = 0;
context = malloc( sizeof( __DAProbeCallbackContext ) );
if ( context == NULL )
{
status = ENOMEM;
goto DAProbeErr;
}
candidates = CFArrayCreateMutableCopy( kCFAllocatorDefault, 0, gDAFileSystemProbeList );
if ( candidates == NULL )
{
status = ENOMEM;
goto DAProbeErr;
}
size = DADiskGetDescription( disk, kDADiskDescriptionMediaSizeKey );
if ( size )
{
if ( ___CFNumberGetIntegerValue( size ) == 0 )
{
CFArrayRemoveAllValues( candidates );
}
}
CFRetain( disk );
context->callback = callback;
context->callbackContext = callbackContext;
context->candidates = candidates;
context->disk = disk;
context->filesystem = NULL;
__DAProbeCallback( -1, NULL, NULL, NULL, NULL, context );
DAProbeErr:
if ( status )
{
if ( candidates )
{
CFRelease( candidates );
}
if ( context )
{
free( context );
}
if ( callback )
{
( callback )( status, NULL, NULL, NULL, NULL, NULL, callbackContext );
}
}
}