-static CFArrayRef
-split_path(CFStringRef path)
-{
- CFArrayRef components;
- CFMutableStringRef nPath;
-
- // turn '@'s into '/'s
- nPath = CFStringCreateMutableCopy(NULL, 0, path);
- (void) CFStringFindAndReplace(nPath,
- CFSTR("@"),
- CFSTR("/"),
- CFRangeMake(0, CFStringGetLength(nPath)),
- 0);
-
- // split path into components to be compared
- components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
- CFRelease(nPath);
-
- return components;
-}
-
-
-static CFComparisonResult
-if_path_compare(const void *val1, const void *val2, void *context)
-{
- CFBooleanRef builtin;
- Boolean builtin_val1 = FALSE;
- Boolean builtin_val2 = FALSE;
- CFArrayRef elements1 = NULL;
- CFArrayRef elements2 = NULL;
- CFIndex i;
- CFIndex n;
- CFIndex n1 = 0;
- CFIndex n2 = 0;
- CFStringRef path;
- CFComparisonResult res;
- CFNumberRef type1;
- CFNumberRef type2;
-
- /* sort by interface type */
-
- type1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOInterfaceType));
- type2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOInterfaceType));
- res = CFNumberCompare(type1, type2, NULL);
- if (res != kCFCompareEqualTo) {
- return (res);
- }
-
- /* built-in interfaces sort first */
- builtin = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOBuiltin));
- if (isA_CFBoolean(builtin) != NULL) {
- builtin_val1 = CFBooleanGetValue(builtin);
- }
- builtin = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOBuiltin));
- if (isA_CFBoolean(builtin) != NULL) {
- builtin_val2 = CFBooleanGetValue(builtin);
- }
- if (builtin_val1 != builtin_val2) {
- if (builtin_val1) {
- res = kCFCompareLessThan;
- } else {
- res = kCFCompareGreaterThan;
- }
- return (res);
- }
-
- /* ... and then sort built-in interfaces by "location" */
- if (builtin_val1) {
- CFStringRef location1;
- CFStringRef location2;
-
- location1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOLocation));
- location2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOLocation));
- if (location1 != location2) {
- if (isA_CFString(location1)) {
- if (isA_CFString(location2)) {
- res = CFStringCompare(location1, location2, 0);
- } else {
- res = kCFCompareLessThan;
- }
- } else {
- res = kCFCompareGreaterThan;
- }
-
- if (res != kCFCompareEqualTo) {
- return (res);
- }
- }
- }
-
- /* ... and then sort by IOPathMatch */
-
- path = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOPathMatchKey));
- if (isA_CFString(path)) {
- elements1 = split_path(path);
- n1 = CFArrayGetCount(elements1);
- } else {
- goto done;
- }
-
- path = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOPathMatchKey));
- if (isA_CFString(path)) {
- elements2 = split_path(path);
- n2 = CFArrayGetCount(elements2);
- } else {
- goto done;
- }
-
- n = (n1 <= n2) ? n1 : n2;
- for (i = 0; i < n; i++) {
- CFStringRef e1;
- CFStringRef e2;
- char *end;
- quad_t q1;
- quad_t q2;
- char *str;
- Boolean isNum;
-
- e1 = CFArrayGetValueAtIndex(elements1, i);
- e2 = CFArrayGetValueAtIndex(elements2, i);
-
- str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingASCII);
- errno = 0;
- q1 = strtoq(str, &end, 16);
- isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
- CFAllocatorDeallocate(NULL, str);
-
- if (isNum) {
- // if e1 is a valid numeric string
- str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingASCII);
- errno = 0;
- q2 = strtoq(str, &end, 16);
- isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
- CFAllocatorDeallocate(NULL, str);
-
- if (isNum) {
- // if e2 is also a valid numeric string
-
- if (q1 == q2) {
- res = kCFCompareEqualTo;
- continue;
- } else if (q1 < q2) {
- res = kCFCompareLessThan;
- } else {
- res = kCFCompareGreaterThan;
- }
- break;
- }
- }
-
- res = CFStringCompare(e1, e2, 0);
- if (res != kCFCompareEqualTo) {
- break;
- }
- }
-
- if (res == kCFCompareEqualTo) {
- if (n1 < n2) {
- res = kCFCompareLessThan;
- } else if (n1 < n2) {
- res = kCFCompareGreaterThan;
- }
- }
-
- done :
- if ( elements1 ) CFRelease( elements1 );
- if ( elements2 ) CFRelease( elements2 );
-
- return res;
-}
-
-static boolean_t
-addCFStringProperty( CFMutableDictionaryRef dict,
- const char * key,
- const char * string )
-{
- boolean_t ret = false;
- CFStringRef valObj, keyObj;
-
- if ( (string == 0) || (key == 0) || (dict == 0) )
- return false;
-
- keyObj = CFStringCreateWithCString(NULL,
- key,
- kCFStringEncodingASCII );
-
- valObj = CFStringCreateWithCString(NULL,
- string,
- kCFStringEncodingASCII );
-
- if (valObj && keyObj) {
- CFDictionarySetValue( dict, keyObj, valObj );
- ret = true;
- }
-
- if ( keyObj ) CFRelease( keyObj );
- if ( valObj ) CFRelease( valObj );
-
- return ret;
-}
-
-static boolean_t
-addCFNumberProperty( CFMutableDictionaryRef dict,
- const char * key,
- unsigned int number )
-{
- boolean_t ret = false;
- CFNumberRef numObj;
- CFStringRef keyObj;
-
- if ( (key == 0) || (dict == 0) )
- return false;
-
- numObj = CFNumberCreate(NULL,
- kCFNumberLongType,
- &number);
-
- keyObj = CFStringCreateWithCString(NULL,
- key,
- kCFStringEncodingASCII );
-
- if ( numObj && keyObj )
- {
- CFDictionarySetValue( dict, keyObj, numObj );
- ret = true;
- }
-
- if ( numObj ) CFRelease( numObj );
- if ( keyObj ) CFRelease( keyObj );
-
- return ret;
-}
-