#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <mach/mach_init.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOBSD.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/storage/IOMedia.h>
#include "GetRegistry.h"
#include "FSParticular.h"
#include "DiskArbitrationServerMain.h"
typedef enum
{
kDriveTypeUnknown = 0x00,
kDriveTypeHD = 0x01,
kDriveTypeCD = 0x02,
kDriveTypeMO = 0x03,
kDriveTypeDVD = 0x04
} DriveType;
DriveType GetDriveType(io_registry_entry_t media);
void GetDisksFromRegistry(io_iterator_t iter)
{
kern_return_t kr;
io_registry_entry_t entry;
io_name_t ioMediaName;
UInt32 ioBSDUnit;
int ioWhole, ioWritable, ioEjectable, ioLeaf;
DriveType driveType;
unsigned flags;
mach_port_t masterPort;
mach_timespec_t timeSpec;
timeSpec.tv_sec = 5;
timeSpec.tv_nsec = 5;
IOMasterPort(bootstrap_port, &masterPort);
IOKitWaitQuiet(masterPort , &timeSpec);
while ( entry = IOIteratorNext( iter ) )
{
char * ioBSDName = NULL; char * ioContent = NULL;
CFBooleanRef boolean = 0; CFNumberRef number = 0; CFDictionaryRef properties = 0; CFStringRef string = 0;
io_string_t ioDeviceTreePath;
char * ioDeviceTreePathPtr;
kr = IORegistryEntryGetName(entry, ioMediaName);
if ( KERN_SUCCESS != kr )
{
dwarning(("can't obtain name for media object\n"));
goto Next;
}
kr = IORegistryEntryCreateCFProperties(entry, &properties, kCFAllocatorDefault, kNilOptions);
if ( KERN_SUCCESS != kr )
{
dwarning(("can't obtain properties for '%s'\n", ioMediaName));
goto Next;
}
assert(CFGetTypeID(properties) == CFDictionaryGetTypeID());
string = (CFStringRef) CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey));
if ( ! string )
{
dwarning(("kIOBSDNameKey property missing for '%s'\n", ioMediaName));
goto Next;
}
assert(CFGetTypeID(string) == CFStringGetTypeID());
ioBSDName = daCreateCStringFromCFString(string);
assert(ioBSDName);
dwarning(("ioBSDName = '%s'\t", ioBSDName));
number = (CFNumberRef) CFDictionaryGetValue(properties, CFSTR(kIOBSDUnitKey));
if ( ! number )
{
dwarning(("\nkIOBSDUnitKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(number) == CFNumberGetTypeID());
if ( ! CFNumberGetValue(number, kCFNumberSInt32Type, &ioBSDUnit) )
{
goto Next;
}
dwarning(("ioBSDUnit = %ld\t", ioBSDUnit));
string = (CFStringRef) CFDictionaryGetValue(properties, CFSTR(kIOMediaContentKey));
if ( ! string )
{
dwarning(("\nkIOMediaContentKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(string) == CFStringGetTypeID());
ioContent = daCreateCStringFromCFString(string);
assert(ioContent);
dwarning(("ioContent = '%s'\t", ioContent));
boolean = (CFBooleanRef) CFDictionaryGetValue(properties, CFSTR(kIOMediaLeafKey));
if ( ! boolean )
{
dwarning(("\nkIOMediaLeafKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(boolean) == CFBooleanGetTypeID());
ioLeaf = ( kCFBooleanTrue == boolean );
dwarning(("ioLeaf = %d\t", ioLeaf));
boolean = (CFBooleanRef) CFDictionaryGetValue(properties, CFSTR(kIOMediaWholeKey));
if ( ! boolean )
{
dwarning(("\nkIOMediaWholeKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(boolean) == CFBooleanGetTypeID());
ioWhole = ( kCFBooleanTrue == boolean );
dwarning(("ioWhole = %d\t", ioWhole));
boolean = (CFBooleanRef) CFDictionaryGetValue(properties, CFSTR(kIOMediaWritableKey));
if ( ! boolean )
{
dwarning(("\nkIOMediaWritableKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(boolean) == CFBooleanGetTypeID());
ioWritable = ( kCFBooleanTrue == boolean );
dwarning(("ioWritable = %d\t", ioWritable));
boolean = (CFBooleanRef) CFDictionaryGetValue(properties, CFSTR(kIOMediaEjectableKey));
if ( ! boolean )
{
dwarning(("\nkIOMediaEjectableKey property missing for '%s'\n", ioBSDName));
goto Next;
}
assert(CFGetTypeID(boolean) == CFBooleanGetTypeID());
ioEjectable = ( kCFBooleanTrue == boolean );
dwarning(("ioEjectable = %d\t", ioEjectable));
kr = IORegistryEntryGetPath( entry, kIODeviceTreePlane, ioDeviceTreePath );
if ( kr )
{
ioDeviceTreePathPtr = NULL;
}
else
{
dwarning(( "ioDeviceTreePath = '%s'\t", ioDeviceTreePath ));
if ( strlen( ioDeviceTreePath ) < strlen( "IODeviceTree:" ) )
{
dwarning(( "\nERROR: expected leading 'IODeviceTree:' in ioDeviceTreePath\n"));
ioDeviceTreePathPtr = ioDeviceTreePath;
}
else
{
ioDeviceTreePathPtr = ioDeviceTreePath + strlen( "IODeviceTree:" );
dwarning(( "\ntrimmed ioDeviceTreePath = '%s'\n", ioDeviceTreePathPtr ));
}
}
flags = 0;
if ( ! ioWritable )
flags |= kDiskArbDiskAppearedLockedMask;
if ( ioEjectable )
flags |= kDiskArbDiskAppearedEjectableMask;
if ( ioWhole )
flags |= kDiskArbDiskAppearedWholeDiskMask;
if ( ! ioLeaf )
flags |= kDiskArbDiskAppearedNonLeafDiskMask;
driveType = GetDriveType( entry );
switch ( driveType )
{
case kDriveTypeHD:
break;
case kDriveTypeCD:
flags |= kDiskArbDiskAppearedCDROMMask;
break;
case kDriveTypeMO:
break;
case kDriveTypeDVD:
flags |= kDiskArbDiskAppearedDVDROMMask;
break;
case kDriveTypeUnknown:
break;
default:
break;
}
if (!shouldAutomount(entry)) {
flags |= kDiskArbDiskAppearedNoMountMask;
}
{
DiskPtr dp;
dp = LookupDiskByIOBSDName( ioBSDName );
if ( dp )
{
dwarning(("%s: '%s' already exists\n", __FUNCTION__, ioBSDName));
if ( dp->mountpoint && 0==strcmp(dp->mountpoint,"") )
{
dp->state = kDiskStateNew;
}
}
else
{
if ( ! NewDisk( ioBSDName,
ioBSDUnit,
ioContent,
kDiskFamily_SCSI,
NULL,
ioMediaName,
ioDeviceTreePathPtr,
entry,
flags ) )
{
LogErrorMessage("%s: NewDisk() failed!\n", __FUNCTION__);
}
}
}
Next:
if ( properties ) CFRelease( properties );
if ( ioBSDName ) free( ioBSDName );
if ( ioContent ) free( ioContent );
}
}
DriveType GetDriveType(io_registry_entry_t media)
{
io_registry_entry_t parent = 0; io_iterator_t parents = 0; io_registry_entry_t service = media; DriveType type = kDriveTypeUnknown; kern_return_t kr;
while ( service )
{
kr = IORegistryEntryGetParentIterator( service, kIOServicePlane, & parents );
if ( kr != KERN_SUCCESS ) break;
if ( parent ) IOObjectRelease( parent );
parent = IOIteratorNext( parents );
if ( parent == 0 ) break;
if ( IOObjectConformsTo( parent, "IOBlockStorageDriver" ) ) break;
IOObjectRelease( parents );
parents = 0;
service = parent;
}
if ( parent )
{
if ( IOObjectConformsTo( parent, "IODVDBlockStorageDriver" ) )
{
dwarning(("DriveType = DVD\n"));
type = kDriveTypeDVD;
}
else if ( IOObjectConformsTo( parent, "IOMOBlockStorageDriver" ) )
{
dwarning(("DriveType = MO\n"));
type = kDriveTypeMO;
}
else if ( IOObjectConformsTo( parent, "IOCDBlockStorageDriver" ) )
{
dwarning(("DriveType = CD\n"));
type = kDriveTypeCD;
}
else
{
dwarning(("DriveType = HD\n"));
type = kDriveTypeHD;
}
IOObjectRelease( parent );
}
if ( parents ) IOObjectRelease( parents );
return type;
}
int shouldAutomount(io_registry_entry_t media)
{
io_registry_entry_t parent = 0; io_iterator_t parents = 0; io_registry_entry_t service = media; kern_return_t kr;
int mount = 1;
while ( service )
{
kr = IORegistryEntryGetParentIterator( service, kIOServicePlane, & parents );
if ( kr != KERN_SUCCESS ) break;
if ( parent ) IOObjectRelease( parent );
parent = IOIteratorNext( parents );
if ( parent == 0 ) break;
if ( IOObjectConformsTo( parent, "IOHDIXHDDriveNub" ) )
{
CFDictionaryRef properties = 0; CFBooleanRef boolean = 0;
kr = IORegistryEntryCreateCFProperties(parent, &properties, kCFAllocatorDefault, kNilOptions);
assert(CFGetTypeID(properties) == CFDictionaryGetTypeID());
boolean = (CFBooleanRef) CFDictionaryGetValue(properties, CFSTR("autodiskmount"));
assert(CFGetTypeID(boolean) == CFBooleanGetTypeID());
if (!( kCFBooleanTrue == boolean )) {
mount = 0;
}
break;
}
IOObjectRelease( parents );
parents = 0;
service = parent;
}
if ( parent ) IOObjectRelease( parent );
if ( parents ) IOObjectRelease( parents );
return mount;
}