BLGetParentDevice.c [plain text]
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/mount.h>
#import <mach/mach_error.h>
#import <IOKit/IOKitLib.h>
#import <IOKit/IOBSD.h>
#import <IOKit/storage/IOMedia.h>
#import <IOKit/storage/IOPartitionScheme.h>
#include <CoreFoundation/CoreFoundation.h>
#include "bless.h"
#include "bless_private.h"
int BLGetParentDevice(BLContextPtr context, const char * partitionDev,
char * parentDev,
uint32_t *partitionNum) {
return BLGetParentDeviceAndPartitionType(context, partitionDev, parentDev, partitionNum, NULL);
}
int BLGetParentDeviceAndPartitionType(BLContextPtr context, const char * partitionDev,
char * parentDev,
uint32_t *partitionNum,
BLPartitionType *partitionType) {
int result = 0;
kern_return_t kret;
io_iterator_t services = MACH_PORT_NULL;
io_iterator_t parents = MACH_PORT_NULL;
io_registry_entry_t service = MACH_PORT_NULL;
io_iterator_t grandparents = MACH_PORT_NULL;
io_registry_entry_t service2 = MACH_PORT_NULL;
io_object_t obj = MACH_PORT_NULL;
CFNumberRef pn = NULL;
CFStringRef content = NULL;
char par[MNAMELEN];
parentDev[0] = '\0';
kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
IOBSDNameMatching(kIOMasterPortDefault,
0,
(char *)partitionDev + 5),
&services);
if (kret != KERN_SUCCESS) {
result = 3;
goto finish;
}
obj = IOIteratorNext(services);
if (!obj) {
result = 4;
goto finish;
}
pn = (CFNumberRef)IORegistryEntryCreateCFProperty(obj, CFSTR(kIOMediaPartitionIDKey),
kCFAllocatorDefault, 0);
if(pn == NULL) {
result = 4;
goto finish;
}
if (CFGetTypeID(pn) != CFNumberGetTypeID()) {
result = 5;
goto finish;
}
CFNumberGetValue(pn, kCFNumberSInt32Type, partitionNum);
kret = IORegistryEntryGetParentIterator (obj, kIOServicePlane,
&parents);
if (kret) {
result = 6;
goto finish;
}
while ( (service = IOIteratorNext(parents)) != 0 ) {
kret = IORegistryEntryGetParentIterator (service, kIOServicePlane,
&grandparents);
IOObjectRelease(service);
service = MACH_PORT_NULL;
if (kret) {
result = 6;
goto finish;
}
while ( (service2 = IOIteratorNext(grandparents)) != 0 ) {
if (content) {
CFRelease(content);
content = NULL;
}
if (!IOObjectConformsTo(service2, "IOMedia")) {
IOObjectRelease(service2);
service2 = MACH_PORT_NULL;
continue;
}
content = (CFStringRef)
IORegistryEntryCreateCFProperty(service2,
CFSTR(kIOMediaContentKey),
kCFAllocatorDefault, 0);
if(CFGetTypeID(content) != CFStringGetTypeID()) {
result = 2;
goto finish;
}
if(CFStringCompare(content, CFSTR("Apple_partition_scheme"), 0)
== kCFCompareEqualTo) {
if(partitionType) *partitionType = kBLPartitionType_APM;
} else if(CFStringCompare(content, CFSTR("FDisk_partition_scheme"), 0)
== kCFCompareEqualTo) {
if(partitionType) *partitionType = kBLPartitionType_MBR;
} else if(CFStringCompare(content, CFSTR("GUID_partition_scheme"), 0)
== kCFCompareEqualTo) {
if(partitionType) *partitionType = kBLPartitionType_GPT;
} else {
IOObjectRelease(service2);
service2 = MACH_PORT_NULL;
CFRelease(content);
content = NULL;
continue;
}
CFRelease(content);
content = IORegistryEntryCreateCFProperty(service2, CFSTR(kIOBSDNameKey),
kCFAllocatorDefault, 0);
if(CFGetTypeID(content) != CFStringGetTypeID()) {
result = 3;
goto finish;
}
if(!CFStringGetCString(content, par, MNAMELEN, kCFStringEncodingASCII)) {
result = 4;
goto finish;
}
CFRelease(content);
content = NULL;
sprintf(parentDev, "/dev/%s",par);
break;
}
if(parentDev[0] == '\0') {
break;
}
}
if(parentDev[0] == '\0') {
result = 8;
goto finish;
}
finish:
if (services != MACH_PORT_NULL) IOObjectRelease(services);
if (parents != MACH_PORT_NULL) IOObjectRelease(parents);
if (service != MACH_PORT_NULL) IOObjectRelease(service);
if (grandparents != MACH_PORT_NULL) IOObjectRelease(grandparents);
if (service2 != MACH_PORT_NULL) IOObjectRelease(service2);
if (obj != MACH_PORT_NULL) IOObjectRelease(obj);
if (pn) CFRelease(pn);
if (content) CFRelease(content);
return result;
}