#include "DADisk.h"
#include "DABase.h"
#include "DAInternal.h"
#include "DALog.h"
#include <grp.h>
#include <paths.h>
#include <pwd.h>
#include <CoreFoundation/CFRuntime.h>
#include <DiskArbitration/DiskArbitrationPrivate.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOBlockStorageDevice.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOCDMedia.h>
#include <IOKit/storage/IODVDMedia.h>
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
struct __DADisk
{
CFRuntimeBase _base;
CFAbsoluteTime _busy;
io_object_t _busyNotification;
CFURLRef _bypath;
DACallbackRef _claim;
CFTypeRef _context;
CFTypeRef _contextRe;
CFMutableDictionaryRef _description;
CFURLRef _device;
char * _deviceLink[2];
dev_t _deviceNode;
char * _devicePath[2];
SInt32 _deviceUnit;
DAFileSystemRef _filesystem;
char * _id;
io_service_t _media;
mode_t _mode;
DADiskOptions _options;
CFDataRef _serialization;
DADiskState _state;
gid_t _userEGID;
uid_t _userEUID;
gid_t _userRGID;
uid_t _userRUID;
};
typedef struct __DADisk __DADisk;
static CFStringRef __DADiskCopyDescription( CFTypeRef object );
static CFStringRef __DADiskCopyFormattingDescription( CFTypeRef object, CFDictionaryRef options );
static void __DADiskDeallocate( CFTypeRef object );
static Boolean __DADiskEqual( CFTypeRef object1, CFTypeRef object2 );
static CFHashCode __DADiskHash( CFTypeRef object );
static const CFRuntimeClass __DADiskClass =
{
0,
"DADisk",
NULL,
NULL,
__DADiskDeallocate,
__DADiskEqual,
__DADiskHash,
__DADiskCopyFormattingDescription,
__DADiskCopyDescription
};
static CFTypeID __kDADiskTypeID = _kCFRuntimeNotATypeID;
extern CFHashCode CFHashBytes( UInt8 * bytes, CFIndex length );
static CFStringRef __DADiskCopyDescription( CFTypeRef object )
{
DADiskRef disk = ( DADiskRef ) object;
return CFStringCreateWithFormat( CFGetAllocator( object ), NULL, CFSTR( "<DADisk %p [%p]>{id = %s}" ), object, CFGetAllocator( object ), disk->_id );
}
static CFStringRef __DADiskCopyFormattingDescription( CFTypeRef object, CFDictionaryRef options )
{
DADiskRef disk = ( DADiskRef ) object;
return CFStringCreateWithFormat( CFGetAllocator( object ), NULL, CFSTR( "%s" ), disk->_id );
}
static DADiskRef __DADiskCreate( CFAllocatorRef allocator, const char * id )
{
__DADisk * disk;
disk = ( void * ) _CFRuntimeCreateInstance( allocator, __kDADiskTypeID, sizeof( __DADisk ) - sizeof( CFRuntimeBase ), NULL );
if ( disk )
{
CFDataRef data;
disk->_busy = 0;
disk->_busyNotification = IO_OBJECT_NULL;
disk->_bypath = NULL;
disk->_claim = NULL;
disk->_context = NULL;
disk->_contextRe = NULL;
disk->_description = CFDictionaryCreateMutable( allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
disk->_device = NULL;
disk->_deviceLink[0] = NULL;
disk->_deviceLink[1] = NULL;
disk->_deviceNode = 0;
disk->_devicePath[0] = NULL;
disk->_devicePath[1] = NULL;
disk->_deviceUnit = -1;
disk->_filesystem = NULL;
disk->_id = strdup( id );
disk->_media = IO_OBJECT_NULL;
disk->_mode = 0;
disk->_options = 0;
disk->_serialization = NULL;
disk->_state = 0;
disk->_userEGID = ___GID_WHEEL;
disk->_userEUID = ___UID_ROOT;
disk->_userRGID = ___GID_WHEEL;
disk->_userRUID = ___UID_ROOT;
assert( disk->_description );
assert( disk->_id );
data = CFDataCreate( allocator, id, strlen( id ) + 1 );
if ( data )
{
CFDictionarySetValue( disk->_description, _kDADiskIDKey, data );
CFRelease( data );
}
}
return disk;
}
static void __DADiskDeallocate( CFTypeRef object )
{
DADiskRef disk = ( DADiskRef ) object;
if ( disk->_busyNotification ) IOObjectRelease( disk->_busyNotification );
if ( disk->_bypath ) CFRelease( disk->_bypath );
if ( disk->_claim ) CFRelease( disk->_claim );
if ( disk->_context ) CFRelease( disk->_context );
if ( disk->_contextRe ) CFRelease( disk->_contextRe );
if ( disk->_description ) CFRelease( disk->_description );
if ( disk->_device ) CFRelease( disk->_device );
if ( disk->_deviceLink[0] ) free( disk->_deviceLink[0] );
if ( disk->_deviceLink[1] ) free( disk->_deviceLink[1] );
if ( disk->_devicePath[0] ) free( disk->_devicePath[0] );
if ( disk->_devicePath[1] ) free( disk->_devicePath[1] );
if ( disk->_filesystem ) CFRelease( disk->_filesystem );
if ( disk->_id ) free( disk->_id );
if ( disk->_media ) IOObjectRelease( disk->_media );
if ( disk->_serialization ) CFRelease( disk->_serialization );
}
static Boolean __DADiskEqual( CFTypeRef object1, CFTypeRef object2 )
{
DADiskRef disk1 = ( DADiskRef ) object1;
DADiskRef disk2 = ( DADiskRef ) object2;
return ( strcmp( disk1->_id, disk2->_id ) == 0 );
}
static CFHashCode __DADiskHash( CFTypeRef object )
{
DADiskRef disk = ( DADiskRef ) object;
return CFHashBytes( disk->_id, MIN( strlen( disk->_id ), 16 ) );
}
static void __DADiskMatch( const void * key, const void * value, void * context )
{
DADiskRef disk = *( ( void * * ) context );
if ( disk )
{
CFTypeRef compare;
compare = CFDictionaryGetValue( disk->_description, key );
if ( CFEqual( key, CFSTR( kIOPropertyMatchKey ) ) )
{
boolean_t match = FALSE;
IOServiceMatchPropertyTable( disk->_media, compare, &match );
if ( match == FALSE )
{
*( ( void * * ) context ) = NULL;
}
}
else
{
if ( compare == NULL || CFEqual( value, compare ) == FALSE )
{
*( ( void * * ) context ) = NULL;
}
}
}
}
CFComparisonResult DADiskCompareDescription( DADiskRef disk, CFStringRef description, CFTypeRef value )
{
CFTypeRef object1 = CFDictionaryGetValue( disk->_description, description );
CFTypeRef object2 = value;
if ( object1 == object2 ) return kCFCompareEqualTo;
if ( object1 == NULL ) return kCFCompareLessThan;
if ( object2 == NULL ) return kCFCompareGreaterThan;
return CFEqual( object1, object2 ) ? kCFCompareEqualTo : kCFCompareLessThan;
}
DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, io_service_t media )
{
io_service_t bus = IO_OBJECT_NULL;
io_service_t device = IO_OBJECT_NULL;
DADiskRef disk = NULL;
UInt32 major;
UInt32 minor;
io_name_t name;
CFMutableDictionaryRef properties = NULL;
CFTypeRef object;
io_string_t path;
io_iterator_t services;
kern_return_t status;
CFDictionaryRef sub;
double time;
status = IORegistryEntryCreateCFProperties( media, &properties, allocator, 0 );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFDictionaryGetValue( properties, CFSTR( kIOBSDNameKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
status = CFStringGetCString( object, name, sizeof( name ), kCFStringEncodingUTF8 );
if ( status == FALSE ) goto DADiskCreateFromIOMediaErr;
strcpy( path, _PATH_DEV );
strcat( path, name );
disk = __DADiskCreate( allocator, path );
if ( disk == NULL ) goto DADiskCreateFromIOMediaErr;
disk->_device = CFURLCreateFromFileSystemRepresentation( allocator, path, strlen( path ), FALSE );
if ( disk->_device == NULL ) goto DADiskCreateFromIOMediaErr;
disk->_devicePath[0] = strdup( path );
strcpy( path, _PATH_DEV );
strcat( path, "r" );
strcat( path, name );
disk->_devicePath[1] = strdup( path );
IOObjectRetain( media );
disk->_media = media;
CFDictionarySetValue( disk->_description, kDADiskDescriptionVolumeNetworkKey, kCFBooleanFalse );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaPreferredBlockSizeKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaBlockSizeKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOBSDNameKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaBSDNameKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOBSDMajorKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaBSDMajorKey, object );
CFNumberGetValue( object, kCFNumberSInt32Type, &major );
object = CFDictionaryGetValue( properties, CFSTR( kIOBSDMinorKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaBSDMinorKey, object );
CFNumberGetValue( object, kCFNumberSInt32Type, &minor );
disk->_deviceNode = makedev( major, minor );
object = CFDictionaryGetValue( properties, CFSTR( kIOBSDUnitKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaBSDUnitKey, object );
CFNumberGetValue( object, kCFNumberSInt32Type, &disk->_deviceUnit );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaContentKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaContentKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaEjectableKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaEjectableKey, object );
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( kIOMediaIconKey ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaIconKey, object );
CFRelease( object );
if ( IOObjectConformsTo( media, kIODVDMediaClass ) )
{
object = CFSTR( kIODVDMediaClass );
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaKindKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIODVDMediaTypeKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaTypeKey, object );
}
else if ( IOObjectConformsTo( media, kIOCDMediaClass ) )
{
object = CFSTR( kIOCDMediaClass );
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaKindKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOCDMediaTypeKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaTypeKey, object );
}
else
{
object = CFSTR( kIOMediaClass );
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaKindKey, object );
}
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaLeafKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaLeafKey, object );
status = IORegistryEntryGetName( media, name );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFStringCreateWithCString( allocator, name, kCFStringEncodingUTF8 );
if ( object == NULL ) object = CFStringCreateWithCString( allocator, name, kCFStringEncodingMacRoman );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaNameKey, object );
CFRelease( object );
status = IORegistryEntryGetPath( media, kIODeviceTreePlane, path );
if ( status != KERN_SUCCESS ) status = IORegistryEntryGetPath( media, kIOServicePlane, path );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFStringCreateWithCString( allocator, path, kCFStringEncodingUTF8 );
if ( object == NULL ) object = CFStringCreateWithCString( allocator, path, kCFStringEncodingMacRoman );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaPathKey, object );
CFRelease( object );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaRemovableKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaRemovableKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaSizeKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaSizeKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaWholeKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaWholeKey, object );
object = CFDictionaryGetValue( properties, CFSTR( kIOMediaWritableKey ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionMediaWritableKey, object );
CFRelease( properties );
properties = NULL;
status = IORegistryEntryCreateIterator( media,
kIOServicePlane,
kIORegistryIterateParents | kIORegistryIterateRecursively,
&services );
while ( ( device = IOIteratorNext( services ) ) )
{
if ( IOObjectConformsTo( device, kIOBlockStorageDeviceClass ) ) break;
IOObjectRelease( device );
}
IOObjectRelease( services );
if ( device == IO_OBJECT_NULL ) goto DADiskCreateFromIOMediaErr;
status = IORegistryEntryCreateCFProperties( device, &properties, allocator, 0 );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
sub = CFDictionaryGetValue( properties, CFSTR( kIOPropertyProtocolCharacteristicsKey ) );
if ( sub )
{
object = CFDictionaryGetValue( sub, CFSTR( kIOPropertyPhysicalInterconnectLocationKey ) );
if ( object )
{
if ( CFStringCompare( object, CFSTR( kIOPropertyInternalKey ), 0 ) == 0 )
{
object = kCFBooleanTrue;
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceInternalKey, object );
}
else if ( CFStringCompare( object, CFSTR( kIOPropertyExternalKey ), 0 ) == 0 )
{
object = kCFBooleanFalse;
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceInternalKey, object );
}
}
object = CFDictionaryGetValue( sub, CFSTR( kIOPropertyPhysicalInterconnectTypeKey ) );
if ( object )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceProtocolKey, object );
}
}
sub = CFDictionaryGetValue( properties, CFSTR( kIOPropertyDeviceCharacteristicsKey ) );
if ( sub )
{
object = CFDictionaryGetValue( sub, CFSTR( kIOPropertyProductNameKey ) );
if ( object )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceModelKey, object );
}
object = CFDictionaryGetValue( sub, CFSTR( kIOPropertyProductRevisionLevelKey ) );
if ( object )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceRevisionKey, object );
}
object = CFDictionaryGetValue( sub, CFSTR( kIOPropertyVendorNameKey ) );
if ( object )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceVendorKey, object );
}
}
status = IORegistryEntryGetPath( device, kIOServicePlane, path );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFStringCreateWithCString( allocator, path, kCFStringEncodingUTF8 );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionDevicePathKey, object );
CFRelease( object );
object = IORegistryEntrySearchCFProperty( device,
kIOServicePlane,
CFSTR( "IOUnit" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceUnitKey, object );
CFRelease( object );
}
object = IORegistryEntrySearchCFProperty( device,
kIOServicePlane,
CFSTR( "GUID" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object )
{
UInt64 value;
CFNumberGetValue( object, kCFNumberSInt64Type, &value );
CFRelease( object );
value = OSSwapHostToBigInt64( value );
object = CFDataCreate( allocator, ( void * ) &value, sizeof( value ) );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionDeviceGUIDKey, object );
CFRelease( object );
}
CFRelease( properties );
properties = NULL;
status = IORegistryEntryCreateIterator( device,
kIOServicePlane,
kIORegistryIterateParents | kIORegistryIterateRecursively,
&services );
while ( ( bus = IOIteratorNext( services ) ) )
{
if ( IORegistryEntryInPlane( bus, kIODeviceTreePlane ) ) break;
IOObjectRelease( bus );
}
IOObjectRelease( services );
if ( bus )
{
status = IORegistryEntryGetNameInPlane( bus, kIODeviceTreePlane, name );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFStringCreateWithCString( allocator, name, kCFStringEncodingUTF8 );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionBusNameKey, object );
CFRelease( object );
status = IORegistryEntryGetPath( bus, kIODeviceTreePlane, path );
if ( status != KERN_SUCCESS ) goto DADiskCreateFromIOMediaErr;
object = CFStringCreateWithCString( allocator, path, kCFStringEncodingUTF8 );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionBusPathKey, object );
CFRelease( object );
IOObjectRelease( bus );
bus = IO_OBJECT_NULL;
}
time = CFAbsoluteTimeGetCurrent( );
object = CFNumberCreate( allocator, kCFNumberDoubleType, &time );
if ( object == NULL ) goto DADiskCreateFromIOMediaErr;
CFDictionarySetValue( disk->_description, kDADiskDescriptionAppearanceTimeKey, object );
CFRelease( object );
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( "autodiskmount" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object == NULL )
{
disk->_options |= kDADiskOptionMountAutomatic;
}
else if ( object == kCFBooleanTrue )
{
disk->_options |= kDADiskOptionMountAutomatic | kDADiskOptionMountAutomaticNoDefer;
}
if ( object ) CFRelease( object );
object = IORegistryEntrySearchCFProperty( device,
kIOServicePlane,
CFSTR( "eject-upon-logout" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object == kCFBooleanTrue )
{
disk->_options |= kDADiskOptionEjectUponLogout;
}
if ( object ) CFRelease( object );
object = CFDictionaryGetValue( disk->_description, kDADiskDescriptionMediaRemovableKey );
if ( object == kCFBooleanTrue )
{
disk->_userRGID = ___GID_UNKNOWN;
disk->_userRUID = ___UID_UNKNOWN;
}
object = CFDictionaryGetValue( disk->_description, kDADiskDescriptionDeviceInternalKey );
if ( object == kCFBooleanFalse )
{
disk->_userRGID = ___GID_UNKNOWN;
disk->_userRUID = ___UID_UNKNOWN;
}
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( "owner-uid" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object )
{
if ( CFGetTypeID( object ) == CFNumberGetTypeID( ) )
{
int value;
CFNumberGetValue( object, kCFNumberIntType, &value );
disk->_userEUID = value;
disk->_userRUID = value;
}
CFRelease( object );
}
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( "owner-gid" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object )
{
if ( CFGetTypeID( object ) == CFNumberGetTypeID( ) )
{
int value;
CFNumberGetValue( object, kCFNumberIntType, &value );
disk->_userEGID = value;
disk->_userRGID = value;
}
CFRelease( object );
}
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( "owner-mode" ),
allocator,
kIORegistryIterateParents | kIORegistryIterateRecursively );
if ( object )
{
if ( CFGetTypeID( object ) == CFNumberGetTypeID( ) )
{
int value;
CFNumberGetValue( object, kCFNumberIntType, &value );
disk->_mode = value;
}
CFRelease( object );
}
object = IORegistryEntrySearchCFProperty( media,
kIOServicePlane,
CFSTR( "dev-name" ),
allocator,
0 );
if ( object )
{
if ( CFGetTypeID( object ) == CFStringGetTypeID( ) )
{
if ( CFStringGetCString( object, name, sizeof( name ), kCFStringEncodingUTF8 ) )
{
strcpy( path, _PATH_DEV );
strcat( path, name );
disk->_deviceLink[0] = strdup( path );
strcpy( path, _PATH_DEV );
strcat( path, "r" );
strcat( path, name );
disk->_deviceLink[1] = strdup( path );
}
}
CFRelease( object );
}
IOObjectRelease( device );
return disk;
DADiskCreateFromIOMediaErr:
if ( IORegistryEntryGetPath( media, kIOServicePlane, path ) == KERN_SUCCESS )
{
DALogError( "unable to create disk, id = %s.", disk ? DADiskGetID( disk ) : NULL );
}
if ( bus ) IOObjectRelease( bus );
if ( device ) IOObjectRelease( device );
if ( disk ) CFRelease( disk );
if ( properties ) CFRelease( properties );
return NULL;
}
DADiskRef DADiskCreateFromVolumePath( CFAllocatorRef allocator, const struct statfs * fs )
{
DADiskRef disk;
disk = NULL;
if ( fs )
{
CFURLRef path;
path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, fs->f_mntonname, strlen( fs->f_mntonname ), TRUE );
if ( path )
{
char * id;
id = _DAVolumeCopyID( fs );
if ( id )
{
disk = __DADiskCreate( allocator, id );
if ( disk )
{
struct passwd * user;
disk->_bypath = CFRetain( path );
CFDictionarySetValue( disk->_description, kDADiskDescriptionVolumePathKey, path );
CFDictionarySetValue( disk->_description, kDADiskDescriptionVolumeMountableKey, kCFBooleanTrue );
if ( ( fs->f_flags & MNT_LOCAL ) )
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionVolumeNetworkKey, kCFBooleanFalse );
}
else
{
CFDictionarySetValue( disk->_description, kDADiskDescriptionVolumeNetworkKey, kCFBooleanTrue );
}
disk->_state |= kDADiskStateStagedProbe;
disk->_state |= kDADiskStateStagedPeek;
disk->_state |= kDADiskStateStagedRepair;
disk->_state |= kDADiskStateStagedApprove;
disk->_state |= kDADiskStateStagedAuthorize;
disk->_state |= kDADiskStateStagedMount;
user = getpwuid( fs->f_owner );
if ( user )
{
disk->_userEGID = user->pw_gid;
disk->_userEUID = user->pw_uid;
disk->_userRGID = user->pw_gid;
disk->_userRUID = user->pw_uid;
}
}
free( id );
}
CFRelease( path );
}
}
return disk;
}
CFAbsoluteTime DADiskGetBusy( DADiskRef disk )
{
return disk->_busy;
}
io_object_t DADiskGetBusyNotification( DADiskRef disk )
{
return disk->_busyNotification;
}
CFURLRef DADiskGetBypath( DADiskRef disk )
{
return disk->_bypath;
}
const char * DADiskGetBSDLink( DADiskRef disk, Boolean raw )
{
return disk->_deviceLink[ raw ? 1 : 0 ];
}
dev_t DADiskGetBSDNode( DADiskRef disk )
{
return disk->_deviceNode;
}
const char * DADiskGetBSDPath( DADiskRef disk, Boolean raw )
{
return disk->_devicePath[ raw ? 1 : 0 ];
}
UInt32 DADiskGetBSDUnit( DADiskRef disk )
{
return disk->_deviceUnit;
}
DACallbackRef DADiskGetClaim( DADiskRef disk )
{
return disk->_claim;
}
CFTypeRef DADiskGetContext( DADiskRef disk )
{
return disk->_context;
}
CFTypeRef DADiskGetContextRe( DADiskRef disk )
{
return disk->_contextRe;
}
CFTypeRef DADiskGetDescription( DADiskRef disk, CFStringRef description )
{
return CFDictionaryGetValue( disk->_description, description );
}
CFURLRef DADiskGetDevice( DADiskRef disk )
{
return disk->_device;
}
DAFileSystemRef DADiskGetFileSystem( DADiskRef disk )
{
return disk->_filesystem;
}
const char * DADiskGetID( DADiskRef disk )
{
return disk->_id;
}
io_service_t DADiskGetIOMedia( DADiskRef disk )
{
return disk->_media;
}
mode_t DADiskGetMode( DADiskRef disk )
{
mode_t mode;
mode = disk->_mode;
if ( DADiskGetDescription( disk, kDADiskDescriptionMediaWritableKey ) == kCFBooleanFalse )
{
mode &= 0555;
}
return mode;
}
Boolean DADiskGetOption( DADiskRef disk, DADiskOption option )
{
return ( disk->_options & option ) ? TRUE : FALSE;
}
DADiskOptions DADiskGetOptions( DADiskRef disk )
{
return disk->_options;
}
CFDataRef DADiskGetSerialization( DADiskRef disk )
{
if ( disk->_serialization == NULL )
{
disk->_serialization = _DASerializeDiskDescription( CFGetAllocator( disk ), disk->_description );
}
return disk->_serialization;
}
Boolean DADiskGetState( DADiskRef disk, DADiskState state )
{
return ( disk->_state & state ) ? TRUE : FALSE;
}
CFTypeID DADiskGetTypeID( void )
{
return __kDADiskTypeID;
}
gid_t DADiskGetUserEGID( DADiskRef disk )
{
return disk->_userEGID;
}
uid_t DADiskGetUserEUID( DADiskRef disk )
{
return disk->_userEUID;
}
gid_t DADiskGetUserRGID( DADiskRef disk )
{
return disk->_userRGID;
}
uid_t DADiskGetUserRUID( DADiskRef disk )
{
return disk->_userRUID;
}
void DADiskInitialize( void )
{
__kDADiskTypeID = _CFRuntimeRegisterClass( &__DADiskClass );
}
void DADiskLog( DADiskRef disk )
{
if ( DADiskGetDescription( disk, kDADiskDescriptionMediaRemovableKey ) == kCFBooleanFalse )
{
if ( DADiskGetDescription( disk, kDADiskDescriptionVolumeMountableKey ) == kCFBooleanTrue )
{
CFMutableStringRef string;
string = CFStringCreateMutable( kCFAllocatorDefault, 0 );
if ( string )
{
CFTypeRef component;
component = DADiskGetDescription( disk, kDADiskDescriptionMediaBSDNameKey );
CFStringAppend( string, component );
___CFStringPad( string, CFSTR( " " ), 10, 0 );
CFStringAppend( string, CFSTR( " " ) );
component = DADiskGetDescription( disk, kDADiskDescriptionVolumeKindKey );
if ( component )
{
CFStringAppend( string, component );
}
___CFStringPad( string, CFSTR( " " ), 19, 0 );
CFStringAppend( string, CFSTR( " " ) );
component = DADiskGetDescription( disk, kDADiskDescriptionVolumeUUIDKey );
if ( component == NULL )
{
component = ___kCFUUIDNull;
}
component = CFUUIDCreateString( kCFAllocatorDefault, component );
if ( component )
{
CFStringAppend( string, component );
CFRelease( component );
}
___CFStringPad( string, CFSTR( " " ), 56, 0 );
CFStringAppend( string, CFSTR( " " ) );
component = DADiskGetDescription( disk, kDADiskDescriptionVolumeNameKey );
if ( component )
{
CFStringAppend( string, component );
}
___CFStringPad( string, CFSTR( " " ), 80, 0 );
CFStringAppend( string, CFSTR( " " ) );
component = DADiskGetDescription( disk, kDADiskDescriptionVolumePathKey );
if ( component )
{
component = CFURLCopyFileSystemPath( component, kCFURLPOSIXPathStyle );
if ( component )
{
CFStringAppend( string, component );
CFRelease( component );
}
}
else
{
CFStringAppend( string, CFSTR( "[not mounted]" ) );
}
DALog( "%@", string );
CFRelease( string );
}
}
}
}
Boolean DADiskMatch( DADiskRef disk, CFDictionaryRef match )
{
CFDictionaryApplyFunction( match, __DADiskMatch, &disk );
return disk ? TRUE : FALSE;
}
void DADiskSetBusy( DADiskRef disk, CFAbsoluteTime busy )
{
disk->_busy = busy;
}
void DADiskSetBusyNotification( DADiskRef disk, io_object_t notification )
{
if ( disk->_busyNotification )
{
IOObjectRelease( disk->_busyNotification );
disk->_busyNotification = IO_OBJECT_NULL;
}
if ( notification )
{
IOObjectRetain( notification );
disk->_busyNotification = notification;
}
}
void DADiskSetBypath( DADiskRef disk, CFURLRef bypath )
{
if ( disk->_bypath )
{
CFRelease( disk->_bypath );
disk->_bypath = NULL;
}
if ( bypath )
{
CFRetain( bypath );
disk->_bypath = bypath;
}
}
void DADiskSetBSDLink( DADiskRef disk, Boolean raw, const char * link )
{
if ( disk->_deviceLink[ raw ? 1 : 0 ] )
{
free( disk->_deviceLink[ raw ? 1 : 0 ] );
disk->_deviceLink[ raw ? 1 : 0 ] = NULL;
}
if ( link )
{
disk->_deviceLink[ raw ? 1 : 0 ] = strdup( link );
}
}
void DADiskSetClaim( DADiskRef disk, DACallbackRef claim )
{
if ( disk->_claim )
{
CFRelease( disk->_claim );
disk->_claim = NULL;
}
if ( claim )
{
CFRetain( claim );
disk->_claim = claim;
}
}
void DADiskSetContext( DADiskRef disk, CFTypeRef context )
{
if ( disk->_context )
{
CFRelease( disk->_context );
disk->_context = NULL;
}
if ( context )
{
CFRetain( context );
disk->_context = context;
}
}
void DADiskSetContextRe( DADiskRef disk, CFTypeRef context )
{
if ( disk->_contextRe )
{
CFRelease( disk->_contextRe );
disk->_contextRe = NULL;
}
if ( context )
{
CFRetain( context );
disk->_contextRe = context;
}
}
void DADiskSetDescription( DADiskRef disk, CFStringRef description, CFTypeRef value )
{
if ( value )
{
CFDictionarySetValue( disk->_description, description, value );
}
else
{
CFDictionaryRemoveValue( disk->_description, description );
}
if ( disk->_serialization )
{
CFRelease( disk->_serialization );
disk->_serialization = NULL;
}
}
void DADiskSetFileSystem( DADiskRef disk, DAFileSystemRef filesystem )
{
if ( disk->_filesystem )
{
CFRelease( disk->_filesystem );
disk->_filesystem = NULL;
}
if ( filesystem )
{
CFRetain( filesystem );
disk->_filesystem = filesystem;
}
}
void DADiskSetOption( DADiskRef disk, DADiskOption option, Boolean value )
{
DADiskSetOptions( disk, option, value );
}
void DADiskSetOptions( DADiskRef disk, DADiskOptions options, Boolean value )
{
disk->_options &= ~options;
disk->_options |= value ? options : 0;
}
void DADiskSetState( DADiskRef disk, DADiskState state, Boolean value )
{
disk->_state &= ~state;
disk->_state |= value ? state : 0;
}
void DADiskSetUserEGID( DADiskRef disk, gid_t userGID )
{
disk->_userEGID = userGID;
}
void DADiskSetUserEUID( DADiskRef disk, uid_t userUID )
{
disk->_userEUID = userUID;
}