off_t diskfile_device_size(const char *path) { // Get the path within /dev if (strncmp(path, DEV_PREFIX, strlen(DEV_PREFIX)) != 0) return 0; const char *bsdname = path + strlen(DEV_PREFIX); // Find the matching IOService CFMutableDictionaryRef matching = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdname); // Consumes the matching dictionary io_service_t match = IOServiceGetMatchingService(kIOMasterPortDefault, matching); if (!match) return 0; // Get the size property CFNumberRef cfsize = IORegistryEntryCreateCFProperty(match, CFSTR(kIOMediaSizeKey), kCFAllocatorDefault, 0); IOObjectRelease(match); if (!cfsize) return 0; long long size; if (!CFNumberGetValue(cfsize, kCFNumberLongLongType, &size)) return 0; return size; }
/** * Given a BSD device node name, guess its media type */ MythMediaType MediaTypeForBSDName(const char *bsdName) { CFMutableDictionaryRef matchingDict; kern_return_t kernResult; io_iterator_t iter; io_service_t service; QString msg = QString("MediaTypeForBSDName(%1)") .arg(bsdName); MythMediaType mediaType; if (!bsdName || !*bsdName) { LOG(VB_GENERAL, LOG_ALERT, msg + " - No name supplied?"); return MEDIATYPE_UNKNOWN; } matchingDict = IOBSDNameMatching(sMasterPort, 0, bsdName); if (!matchingDict) { LOG(VB_GENERAL, LOG_ALERT, msg + " - IOBSDNameMatching() returned a NULL dictionary."); return MEDIATYPE_UNKNOWN; } // Return an iterator across all objects with the matching // BSD node name. Note that there should only be one match! kernResult = IOServiceGetMatchingServices(sMasterPort, matchingDict, &iter); if (KERN_SUCCESS != kernResult) { LOG(VB_GENERAL, LOG_ALERT, QString(msg + " - IOServiceGetMatchingServices() returned %2") .arg(kernResult)); return MEDIATYPE_UNKNOWN; } if (!iter) { LOG(VB_GENERAL, LOG_ALERT, msg + " - IOServiceGetMatchingServices() returned a NULL " "iterator"); return MEDIATYPE_UNKNOWN; } service = IOIteratorNext(iter); // Release this now because we only expect // the iterator to contain a single io_service_t. IOObjectRelease(iter); if (!service) { LOG(VB_GENERAL, LOG_ALERT, msg + " - IOIteratorNext() returned a NULL iterator"); return MEDIATYPE_UNKNOWN; } mediaType = FindMediaType(service); IOObjectRelease(service); return mediaType; }
/* * Try to record the named device as interesting. It * must be an IOMedia device. */ static int record_one_device(char *name) { io_iterator_t drivelist; io_registry_entry_t drive; kern_return_t status; /* * Find the device. */ status = IOServiceGetMatchingServices(masterPort, IOBSDNameMatching(masterPort, kNilOptions, name), &drivelist); if (status != KERN_SUCCESS) errx(1, "couldn't match '%s'", name); /* * Get the first match (should only be one) */ if ((drive = IOIteratorNext(drivelist)) == NULL) errx(1, "'%s' not found", name); if (!IOObjectConformsTo(drive, "IOMedia")) errx(1, "'%s' is not a storage device", name); /* * Record the device. */ if (record_device(drive)) errx(1, "could not record '%s' for monitoring", name); IOObjectRelease(drive); IOObjectRelease(drivelist); return(0); }
uint16_t OSX_ProbeTargetDrive(const char* id3args_drive, char* mcdi_data) { uint16_t mcdi_data_len = 0; io_object_t cdobject = MACH_PORT_NULL; if (strncmp(id3args_drive, "disk", 4) != 0) { OSX_ScanForCDDrive(); exit(0); } cdobject = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching (kIOMasterPortDefault, 0, id3args_drive) ); if (cdobject == MACH_PORT_NULL) { fprintf(stdout, "No device found at %s; searching for possible drives...\n", id3args_drive); OSX_ScanForCDDrive(); } else if (IOObjectConformsTo(cdobject, kIOCDMediaClass) == false) { fprintf (stdout, "No cd present in drive at %s\n", id3args_drive ); IOObjectRelease(cdobject); cdobject = MACH_PORT_NULL; OSX_ScanForCDDrive(); } else { //we now have a cd object OSX_ReadCDTOC(cdobject); if (cdTOC != NULL) { uint8_t cdType = DetermineCDType(cdTOC); if (cdType == CDOBJECT_AUDIOCD) { mcdi_data_len = FormMCDIdata(mcdi_data); } } } IOObjectRelease(cdobject); cdobject = MACH_PORT_NULL; return mcdi_data_len; }
void genFDEStatusForBSDName(const std::string& bsd_name, const std::string& uuid, QueryData& results) { auto matching_dict = IOBSDNameMatching(kIOMasterPortDefault, kNilOptions, bsd_name.c_str()); if (matching_dict == nullptr) { CFRelease(matching_dict); return; } auto service = IOServiceGetMatchingService(kIOMasterPortDefault, matching_dict); if (!service) { IOObjectRelease(service); return; } CFMutableDictionaryRef properties; IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions); Row r; r["name"] = kDeviceNamePrefix + bsd_name; r["uuid"] = uuid; auto encrypted = getIOKitProperty(properties, kCoreStorageIsEncryptedKey_); r["encrypted"] = (encrypted.empty()) ? "0" : encrypted; r["type"] = (r.at("encrypted") == "1") ? kEncryptionType : std::string(); results.push_back(r); CFRelease(properties); IOObjectRelease(service); }
// Returns an iterator containing the primary (built-in) Ethernet interface. The caller is responsible for // releasing the iterator after the caller is done with it. static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices, char* interfaceName) { kern_return_t kernResult; CFMutableDictionaryRef matchingDict; //CFMutableDictionaryRef propertyMatchDict; // Ethernet interfaces are instances of class kIOEthernetInterfaceClass. // IOServiceMatching is a convenience function to create a dictionary with the key kIOProviderClassKey and // the specified value. // Note by mike: we're not using this method and then filtering by kIOPropertyMatchKey anymore, // because that way we were getting authorization errors for some people for whom, for whatever reason, // kIOPropertyMatchKey was not TRUE for their en0 interface //matchingDict = IOServiceMatching(kIOEthernetInterfaceClass); matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, interfaceName); if (NULL == matchingDict) { printf("IOBSDNameMatching returned a NULL dictionary.\n"); } // IOServiceGetMatchingServices retains the returned iterator, so release the iterator when we're done with it. // IOServiceGetMatchingServices also consumes a reference on the matching dictionary so we don't need to release // the dictionary explicitly. kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices); if (KERN_SUCCESS != kernResult) { printf("IOServiceGetMatchingServices returned 0x%08x\n", kernResult); } return kernResult; }
/* * Given disk2s1, look up "disk2" is IOKit and attempt to determine if * it is an optical device. */ int is_optical_media(const char *bsdname) { CFMutableDictionaryRef matchingDict; int ret = 0; io_service_t service, start; kern_return_t kernResult; io_iterator_t iter; if ((matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdname)) == NULL) return(0); start = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict); if (IO_OBJECT_NULL == start) return (0); service = start; // Create an iterator across all parents of the service object passed in. // since only disk2 would match with ConfirmsTo, and not disk2s1, so // we search the parents until we find "Whole", ie, disk2. kernResult = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); if (KERN_SUCCESS == kernResult) { Boolean isWholeMedia = false; IOObjectRetain(service); do { // Lookup "Whole" if we can if (IOObjectConformsTo(service, kIOMediaClass)) { CFTypeRef wholeMedia; wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0); if (wholeMedia) { isWholeMedia = CFBooleanGetValue(wholeMedia); CFRelease(wholeMedia); } } // If we found "Whole", check the service type. if (isWholeMedia && ( (IOObjectConformsTo(service, kIOCDMediaClass)) || (IOObjectConformsTo(service, kIODVDMediaClass)) )) { ret = 1; // Is optical, skip } IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && !isWholeMedia); IOObjectRelease(iter); } IOObjectRelease(start); return ret; }
void GetAdditionalVolumeInfo(char* bsdName) { // The idea is that given the BSD node name corresponding to a volume, // I/O Kit can be used to find the information about the media, drive, bus, and so on // that is maintained in the IORegistry. // // In this sample, we find out if the volume is on a CD, DVD, or some other media. // This is done as follows: // // 1. Find the IOMedia object that represents the entire (whole) media that the volume is on. // // If the volume is on partitioned media, the whole media object will be a parent of the volume's // media object. If the media is not partitioned, (a floppy disk, for example) the volume's media // object will be the whole media object. // // The whole media object is indicated in the IORegistry by the presence of a property with the key // "Whole" and value "Yes". // // 2. Determine which I/O Kit class the whole media object belongs to. // // For CD media the class name will be "IOCDMedia," and for DVD media the class name will be // "IODVDMedia". Other media will be of the generic "IOMedia" class. // CFMutableDictionaryRef matchingDict; kern_return_t kernResult; io_iterator_t iter; io_service_t service; matchingDict = IOBSDNameMatching(gMasterPort, 0, bsdName); if (NULL == matchingDict) { printf("IOBSDNameMatching returned a NULL dictionary.\n"); } else { // Return an iterator across all objects with the matching BSD node name. Note that there // should only be one match! kernResult = IOServiceGetMatchingServices(gMasterPort, matchingDict, &iter); if (KERN_SUCCESS != kernResult) { printf("IOServiceGetMatchingServices returned %d\n", kernResult); } else if (NULL == iter) { printf("IOServiceGetMatchingServices returned a NULL iterator\n"); } else { service = IOIteratorNext(iter); // Release this now because we only expect the iterator to contain // a single io_service_t. IOObjectRelease(iter); if (NULL == service) { printf("IOIteratorNext returned NULL\n"); } else { FindWholeMedia(service); IOObjectRelease(service); } } } }
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort) { int retval = 0; CFMutableDictionaryRef matchingDict; kern_return_t rc; io_iterator_t iter; io_service_t service; if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL) return(0); rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter); if ((rc != KERN_SUCCESS) || (!iter)) return(0); service = IOIteratorNext(iter); IOObjectRelease(iter); if (!service) return(0); rc = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); if (!iter) return(0); if (rc != KERN_SUCCESS) { IOObjectRelease(iter); return(0); } /* if */ IOObjectRetain(service); /* add an extra object reference... */ do { if (darwinIsWholeMedia(service)) { if ( (IOObjectConformsTo(service, kIOCDMediaClass)) || (IOObjectConformsTo(service, kIODVDMediaClass)) ) { retval = 1; } /* if */ } /* if */ IOObjectRelease(service); } while ((service = IOIteratorNext(iter)) && (!retval)); IOObjectRelease(iter); IOObjectRelease(service); return(retval); } /* darwinIsMountedDisc */
static bool IsEncrypted(const char *bsdname) { bool retval = false; const char *diskname = NULL; CFMutableDictionaryRef ioMatch; //IOServiceGetMatchingService() releases:! io_object_t ioObj = IO_OBJECT_NULL; CFBooleanRef lvfIsEncr = NULL; if (strncmp(bsdname, _PATH_DEV, strlen(_PATH_DEV)) == 0) { diskname = bsdname + strlen(_PATH_DEV); } if (diskname == NULL) goto finish; if (strncmp(diskname, "rdisk", 5) == 0) diskname++; //look up the IOMedia object ioMatch = IOBSDNameMatching(kIOMasterPortDefault, 0, diskname); if (!ioMatch) goto finish; // Setting this allows a fast-path lookup to happen // see 10248763 CFDictionarySetValue(ioMatch, CFSTR(kIOProviderClassKey), CFSTR(kIOMediaClass)); ioObj = IOServiceGetMatchingService(kIOMasterPortDefault, ioMatch); ioMatch = NULL; //IOServiceGetMatching() released ioMatch if (ioObj == IO_OBJECT_NULL) { goto finish; } lvfIsEncr = IORegistryEntryCreateCFProperty(ioObj, CFSTR(kCoreStorageIsEncryptedKey), nil, 0); if (lvfIsEncr == NULL) retval = false; else retval = CFBooleanGetValue(lvfIsEncr); finish: if (lvfIsEncr) CFRelease(lvfIsEncr); if (ioObj != IO_OBJECT_NULL) { IOObjectRelease(ioObj); } return retval; }
void genFDEStatusForBSDName(const std::string& bsd_name, const std::string& uuid, QueryData& results) { auto matching_dict = IOBSDNameMatching(kIOMasterPortDefault, kNilOptions, bsd_name.c_str()); if (matching_dict == nullptr) { return; } auto service = IOServiceGetMatchingService(kIOMasterPortDefault, matching_dict); if (!service) { return; } CFMutableDictionaryRef properties; if (IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions) != KERN_SUCCESS) { IOObjectRelease(service); return; } Row r; r["name"] = kDeviceNamePrefix + bsd_name; r["uuid"] = uuid; auto encrypted = getIOKitProperty(properties, kCoreStorageIsEncryptedKey_); if (encrypted.empty()) { r["encrypted"] = "0"; } else { r["encrypted"] = encrypted; id_t uid; uuid_string_t uuid_string = {0}; if (genUid(uid, uuid_string).ok()) { r["uid"] = BIGINT(uid); r["user_uuid"] = TEXT(uuid_string); } } r["type"] = (r.at("encrypted") == "1") ? kEncryptionType : std::string(); results.push_back(r); CFRelease(properties); IOObjectRelease(service); }
int main(int argc, char *argv[]) { char *path; kern_return_t ret; io_registry_entry_t entry = 0; io_string_t iopath; if(argc != 2) { fprintf(stderr, "Usage: %s disk1s1\n", getprogname()); exit(1); } path = argv[1]; // entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); entry = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, path)); printf("entry is %p\n", entry); if(entry == 0) exit(1); ret = IORegistryEntryGetPath(entry, kIOServicePlane, iopath); if(ret) { fprintf(stderr, "Could not get entry path\n"); exit(1); } printf("%s path: %s\n", kIOServicePlane, iopath); ret = IORegistryEntryGetPath(entry, kIODeviceTreePlane, iopath); if(ret) { fprintf(stderr, "Could not get entry path\n"); exit(1); } printf("%s path: %s\n", kIODeviceTreePlane, iopath); IOObjectRelease(entry); return 0; }
IOReturn IOPMPagingPlexus::setAggressiveness ( unsigned long type, unsigned long ) { OSDictionary * dict; OSIterator * iter; OSObject * next; IOService * candidate = 0; IOService * pagingProvider; if( type != kPMMinutesToSleep) return IOPMNoErr; IOLockLock(ourLock); if ( systemBooting ) { systemBooting = false; IOLockUnlock(ourLock); dict = IOBSDNameMatching(rootdevice); if ( dict ) { iter = getMatchingServices(dict); if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (candidate = OSDynamicCast(IOService,next)) ) { break; } } iter->release(); } } if ( candidate ) { pagingProvider = findProvider(candidate); if ( pagingProvider ) { processSiblings(pagingProvider); pagingProvider->addPowerChild(this); getPMRootDomain()->removePowerChild(((IOPowerConnection *)getParentEntry(gIOPowerPlane))); processChildren(); } } } else { IOLockUnlock(ourLock); } return IOPMNoErr; }
CFDictionaryRef myIORegistryEntryBSDNameMatchingCopyValue(const char * devname, Boolean parent) { kern_return_t status; CFMutableDictionaryRef properties = NULL; io_registry_entry_t service; service = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, devname)); if (service == MACH_PORT_NULL) { return (NULL); } if (parent) { io_registry_entry_t parent_service; status = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent_service); if (status == KERN_SUCCESS) { status = IORegistryEntryCreateCFProperties(parent_service, &properties, kCFAllocatorDefault, kNilOptions); IOObjectRelease(parent_service); } } else { status = IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions); } if (status != KERN_SUCCESS) { properties = NULL; } IOObjectRelease(service); return (properties); }
static IOReturn PrintSMARTDataForBSDNode ( const char * bsdNode ) { IOReturn error = kIOReturnError; io_object_t object = MACH_PORT_NULL; io_object_t parent = MACH_PORT_NULL; bool found = false; char * bsdName = NULL; char deviceName[MAXPATHLEN]; sprintf ( deviceName, "%s", bsdNode ); if ( !strncmp ( deviceName, "/dev/r", 6 ) ) { // Strip off the /dev/r from /dev/rdiskX bsdName = &deviceName[6]; } else if ( !strncmp ( deviceName, "/dev/", 5 ) ) { // Strip off the /dev/r from /dev/rdiskX bsdName = &deviceName[5]; } else { bsdName = deviceName; } require_action ( ( strncmp ( bsdName, "disk", 4 ) == 0 ), ErrorExit, PrintUsage ( ) ); object = IOServiceGetMatchingService ( kIOMasterPortDefault, IOBSDNameMatching ( kIOMasterPortDefault, 0, bsdName ) ); require ( ( object != MACH_PORT_NULL ), ErrorExit ); parent = object; while ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) == false ) { #if DEBUG io_name_t className; error = IOObjectGetClass ( object, className ); printf ( "Object class = %s\n", ( char * ) className ); #endif error = IORegistryEntryGetParentEntry ( object, kIOServicePlane, &parent ); require ( ( error == kIOReturnSuccess ), ReleaseObject ); require ( ( parent != MACH_PORT_NULL ), ReleaseObject ); IOObjectRelease ( object ); object = parent; } if ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) ) { PrintSMARTDataForDevice ( object ); found = true; } ReleaseObject: require ( ( object != MACH_PORT_NULL ), ErrorExit ); IOObjectRelease ( object ); object = MACH_PORT_NULL; ErrorExit: if ( found == false ) { printf ( "No S.M.A.R.T. capable device at %s\n", bsdNode ); } return error; }
void MemoryCardDriverThreaded_MacOSX::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut ) { LockMut( m_ChangedLock ); // First, get all device paths struct statfs *fs; int num = getfsstat( NULL, 0, MNT_NOWAIT ); fs = new struct statfs[num]; num = getfsstat( fs, num * sizeof(struct statfs), MNT_NOWAIT ); ASSERT( num != -1 ); for( int i = 0; i < num; ++i ) { if( strncmp(fs[i].f_mntfromname, _PATH_DEV, strlen(_PATH_DEV)) ) continue; const RString& sDevicePath = fs[i].f_mntfromname; const RString& sDisk = Basename( sDevicePath ); // disk#[[s#] ...] // Now that we have the disk name, look up the IOServices associated with it. CFMutableDictionaryRef dict; if( !(dict = IOBSDNameMatching(kIOMasterPortDefault, 0, sDisk)) ) continue; // Look for certain properties: Leaf, Ejectable, Writable. CFDictionarySetValue( dict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue ); CFDictionarySetValue( dict, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue ); CFDictionarySetValue( dict, CFSTR(kIOMediaWritableKey), kCFBooleanTrue ); // Get the matching iterator. As always, this consumes a reference to dict. io_iterator_t iter; kern_return_t ret = IOServiceGetMatchingServices( kIOMasterPortDefault, dict, &iter ); if( ret != KERN_SUCCESS || iter == 0 ) continue; // I'm not quite sure what it means to have two services with this device. // Iterate over them all. If one contains what we want, stop. io_registry_entry_t device; // This is the same as an io_object_t. while( (device = IOIteratorNext(iter)) ) { // Look at the parent of the device until we see an IOUSBMassStorageClass while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBMassStorageClass") ) { io_registry_entry_t entry; ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry ); IOObjectRelease( device ); device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL; } // Now look for the corresponding IOUSBDevice, it's likely 2 up the tree while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBDevice") ) { io_registry_entry_t entry; ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry ); IOObjectRelease( device ); device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL; } if( device == MACH_PORT_NULL ) continue; // At this point, it is pretty safe to say that we've found a USB device. vDevicesOut.push_back( UsbStorageDevice() ); UsbStorageDevice& usbd = vDevicesOut.back(); LOG->Trace( "Found memory card at path: %s.", fs[i].f_mntonname ); usbd.SetOsMountDir( fs[i].f_mntonname ); usbd.iVolumeSizeMB = int( (uint64_t(fs[i].f_blocks) * fs[i].f_bsize) >> 20 ); // Now we can get some more information from the registry tree. usbd.iBus = GetIntProperty( device, CFSTR("USB Address") ); usbd.iPort = GetIntProperty( device, CFSTR("PortNum") ); // usbd.iLevel ? usbd.sSerial = GetStringProperty( device, CFSTR("USB Serial Number") ); usbd.sDevice = fs[i].f_mntfromname; usbd.idVendor = GetIntProperty( device, CFSTR(kUSBVendorID) ); usbd.idProduct = GetIntProperty( device, CFSTR(kUSBProductID) ); usbd.sVendor = GetStringProperty( device, CFSTR("USB Vendor Name") ); usbd.sProduct = GetStringProperty( device, CFSTR("USB Product Name") ); IOObjectRelease( device ); break; // We found what we wanted } IOObjectRelease( iter ); } m_bChanged = false; delete[] fs; }
IOCDMedia * GetCDMediaObjectFromName ( const char * ioBSDNamePtr ) { OSIterator * iteratorPtr = NULL; IORegistryEntry * registryEntryPtr = NULL; IOCDMedia * objectPtr = NULL; OSDictionary * matchingDictPtr = NULL; DebugLog ( ( "GetCDMediaObjectFromName: Entering...\n" ) ); DebugAssert ( ( ioBSDNamePtr != NULL ) ); DebugLog ( ( "GetCDMediaObjectFromName: On enter ioBSDNamePtr = %s.\n", ioBSDNamePtr ) ); // Check to see if we need to strip off any leading stuff if ( !strncmp ( ioBSDNamePtr, "/dev/r", 6 ) ) { // Strip off the /dev/r from /dev/rdiskX ioBSDNamePtr = &ioBSDNamePtr[6]; } else if ( !strncmp ( ioBSDNamePtr, "/dev/", 5 ) ) { // Strip off the /dev/ from /dev/diskX ioBSDNamePtr = &ioBSDNamePtr[5]; } if ( strncmp ( ioBSDNamePtr, "disk", 4 ) ) { // Not in correct format, return NULL DebugLog ( ( "GetCDMediaObjectFromName: not in correct format, ioBSDNamePtr = %s.\n", ioBSDNamePtr ) ); return NULL; } DebugLog ( ( "GetCDMediaObjectFromName: ioBSDNamePtr = %s.\n", ioBSDNamePtr ) ); // Get a dictionary which describes the bsd device matchingDictPtr = IOBSDNameMatching ( ioBSDNamePtr ); // Get an iterator of registry entries iteratorPtr = IOService::getMatchingServices ( matchingDictPtr ); if ( iteratorPtr == NULL ) { DebugLog ( ( "GetCDMediaObjectFromName: iteratorPtr is NULL.\n" ) ); return NULL; } // Release the dictionary matchingDictPtr->release ( ); DebugLog ( ( "Acquired refcount on iterator and media.\n" ) ); // Get the object out of the iterator (NB: we're guaranteed only one object in the iterator // because there is a 1:1 correspondence between BSD Names for devices and IOKit objects registryEntryPtr = ( IORegistryEntry * ) iteratorPtr->getNextObject ( ); if ( registryEntryPtr == NULL ) { DebugLog ( ( "GetCDMediaObjectFromName: registryEntryPtr is NULL.\n" ) ); return NULL; } // Cast it to the correct type objectPtr = OSDynamicCast ( IOCDMedia, registryEntryPtr ); if ( objectPtr == NULL ) { // Cast failed...spew an error DebugLog ( ( "GetCDMediaObjectFromName: objectPtr is NULL, Dynamic Cast failed.\n" ) ); } DebugLog ( ( "GetCDMediaObjectFromName: exiting...\n" ) ); // Bump the refcount on the CDMedia so that when we release the iterator // we still have a refcount on it. if ( objectPtr != NULL ) { objectPtr->retain ( ); } // Release the iterator iteratorPtr->release ( ); return ( objectPtr ); }
// first look up the media object, then create a // custom matching dictionary that should be persistent // from boot to boot int addMatchingInfoForBSDName(BLContextPtr context, mach_port_t masterPort, CFMutableDictionaryRef dict, const char *bsdName, bool shortForm) { io_service_t media = IO_OBJECT_NULL, checkMedia = IO_OBJECT_NULL; CFStringRef uuid = NULL; CFMutableDictionaryRef propDict = NULL; kern_return_t kret; CFStringRef lastBSDName = NULL; lastBSDName = CFStringCreateWithCString(kCFAllocatorDefault, bsdName, kCFStringEncodingUTF8); propDict = IOBSDNameMatching(masterPort, 0, bsdName); CFDictionarySetValue(propDict, CFSTR(kIOProviderClassKey), CFSTR(kIOMediaClass)); media = IOServiceGetMatchingService(masterPort, propDict); propDict = NULL; if(media == IO_OBJECT_NULL) { contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", bsdName); CFRelease(lastBSDName); return 1; } uuid = IORegistryEntryCreateCFProperty(media, CFSTR(kIOMediaUUIDKey), kCFAllocatorDefault, 0); if(uuid == NULL) { CFUUIDRef fsuuid = NULL; CFStringRef fsuuidstr = NULL; io_string_t path; #if USE_DISKARBITRATION DASessionRef session = NULL; DADiskRef dadisk = NULL; contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a partition %s\n", bsdName, kIOMediaUUIDKey); session = DASessionCreate(kCFAllocatorDefault); if(session) { dadisk = DADiskCreateFromIOMedia(kCFAllocatorDefault, session, media); if(dadisk) { CFDictionaryRef descrip = DADiskCopyDescription(dadisk); if(descrip) { fsuuid = CFDictionaryGetValue(descrip, kDADiskDescriptionVolumeUUIDKey); if(fsuuid) CFRetain(fsuuid); CFRelease(descrip); } CFRelease(dadisk); } CFRelease(session); } #endif // USE_DISKARBITRATION if(fsuuid) { char fsuuidCString[64]; fsuuidstr = CFUUIDCreateString(kCFAllocatorDefault, fsuuid); CFStringGetCString(fsuuidstr,fsuuidCString,sizeof(fsuuidCString),kCFStringEncodingUTF8); contextprintf(context, kBLLogLevelVerbose, "DADiskRef %s has Volume UUID %s\n", bsdName, fsuuidCString); CFRelease(fsuuid); } else { contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a Volume UUID\n", bsdName); } // we have a volume UUID, but our primary matching mechanism will be the device path kret = IORegistryEntryGetPath(media, kIODeviceTreePlane,path); if(kret) { contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have device tree path\n", bsdName); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOBSDNameKey), lastBSDName); // add UUID as hint if(fsuuidstr) CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr); } else { CFStringRef blpath = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has path %s\n", bsdName, path); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOPathMatchKey), blpath); CFRelease(blpath); // add UUID as hint if(fsuuidstr) CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr); CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName); } if(fsuuidstr) { CFRelease(fsuuidstr); } } else { CFMutableDictionaryRef propMatch; contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has UUID %s\n", bsdName, BLGetCStringDescription(uuid)); propMatch = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(propMatch, CFSTR(kIOMediaUUIDKey), uuid); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOPropertyMatchKey), propMatch); CFRelease(propMatch); // add a hint to the top-level dict CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName); CFRelease(uuid); } // verify the dictionary matches CFRetain(propDict); // consumed below checkMedia = IOServiceGetMatchingService(masterPort, propDict); if(IO_OBJECT_NULL == checkMedia || !IOObjectIsEqualTo(media, checkMedia)) { contextprintf(context, kBLLogLevelVerbose, "Inconsistent registry entries for %s\n", bsdName); if(IO_OBJECT_NULL != checkMedia) IOObjectRelease(checkMedia); IOObjectRelease(media); CFRelease(lastBSDName); CFRelease(propDict); return 2; } IOObjectRelease(checkMedia); IOObjectRelease(media); CFDictionaryAddValue(dict, CFSTR("IOMatch"), propDict); CFRelease(lastBSDName); CFRelease(propDict); if(shortForm) { CFDictionaryAddValue(dict, CFSTR("IOEFIShortForm"), kCFBooleanTrue); } return 0; }
// Like open(). Return non-negative integer handle, only used by the // functions below. type=="ATA" or "SCSI". The return value is // an index into the devices[] array. If the device can't be opened, // sets errno and returns -1. // Acceptable device names are: // /dev/disk* // /dev/rdisk* // disk* // IOService:* // IODeviceTree:* int deviceopen(const char *pathname, char *type){ size_t devnum; const char *devname; io_object_t disk; if (strcmp (type, "ATA") != 0) { errno = EINVAL; return -1; } // Find a free device number. for (devnum = 0; devnum < sizeof (devices) / sizeof (devices[0]); devnum++) if (! devices[devnum].ioob) break; if (devnum == sizeof (devices) / sizeof (devices[0])) { errno = EMFILE; return -1; } devname = NULL; if (strncmp (pathname, "/dev/rdisk", 10) == 0) devname = pathname + 6; else if (strncmp (pathname, "/dev/disk", 9) == 0) devname = pathname + 5; else if (strncmp (pathname, "disk", 4) == 0) // allow user to just say 'disk0' devname = pathname; // Find the device. if (devname) { CFMutableDictionaryRef matcher; matcher = IOBSDNameMatching (kIOMasterPortDefault, 0, devname); disk = IOServiceGetMatchingService (kIOMasterPortDefault, matcher); } else { disk = IORegistryEntryFromPath (kIOMasterPortDefault, pathname); } if (! disk) { errno = ENOENT; return -1; } // Find a SMART-capable driver which is a parent of this device. while (! is_smart_capable (disk)) { IOReturn err; io_object_t prevdisk = disk; // Find this device's parent and try again. err = IORegistryEntryGetParentEntry (disk, kIOServicePlane, &disk); if (err != kIOReturnSuccess || ! disk) { errno = ENODEV; IOObjectRelease (prevdisk); return -1; } } devices[devnum].ioob = disk; { SInt32 dummy; devices[devnum].plugin = NULL; devices[devnum].smartIf = NULL; // Create an interface to the ATA SMART library. if (IOCreatePlugInInterfaceForService (disk, kIOATASMARTUserClientTypeID, kIOCFPlugInInterfaceID, &devices[devnum].plugin, &dummy) == kIOReturnSuccess) (*devices[devnum].plugin)->QueryInterface (devices[devnum].plugin, CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID), (void **)&devices[devnum].smartIf); } return devnum; }
FskErr FskFSVolumeGetDeviceInfo(UInt32 volumeID, char **vendor, char **product, char **revision, char **vendorSpecific) { FskErr err = kFskErrNone; mach_port_t masterPort = MACH_PORT_NULL; io_service_t service; io_iterator_t iterator = 0; io_object_t obj; char bsdNode[256]; CFMutableDictionaryRef properties = NULL; Boolean isFound = false; char *p; if (vendor) *vendor = NULL; if (product) *product = NULL; if (revision) *revision = NULL; if (vendorSpecific) *vendorSpecific = NULL; if (volumeID >= (UInt32)gNumStatFS) return kFskErrInvalidParameter; p = gStatFS[volumeID].f_mntfromname; if (FskStrStr(p, "/dev/") == p) p += 5; FskStrCopy(bsdNode, p); err = IOMasterPort(MACH_PORT_NULL, &masterPort); if (err != kIOReturnSuccess) { BAIL(kFskErrUnknown); } err = IOServiceGetMatchingServices(masterPort, IOBSDNameMatching(masterPort, 0, bsdNode), &iterator); if (err != kIOReturnSuccess) { BAIL(kFskErrUnknown); } // There is a 1:1 map from bsd node to IOMedia, so just get the service from the iterator. obj = IOIteratorNext(iterator); IOObjectRelease(iterator); if (obj == 0) goto bail; // Create an iterator across all parents of the service object passed in. err = IORegistryEntryCreateIterator(obj, kIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents, &iterator); IOObjectRelease(obj); if (KERN_SUCCESS != err) { BAIL(kFskErrUnknown); } while ((service = IOIteratorNext(iterator)) != 0) { properties = NULL; err = IORegistryEntryCreateCFProperties(service, &properties, kCFAllocatorDefault, kNilOptions); if (err == noErr) { if (find_and_set_info(properties, CFSTR("Vendor Identification"), vendor)) { find_and_set_info(properties, CFSTR("Product Identification"), product); find_and_set_info(properties, CFSTR("Product Revision Level"), revision); isFound = true; goto NextService; } if (find_and_set_info(properties, CFSTR("device model"), product)) { find_and_set_info(properties, CFSTR("device revision"), revision); isFound = true; goto NextService; } } NextService: if (properties) CFRelease(properties); IOObjectRelease(service); if (isFound) break; } // while bail: if (iterator) IOObjectRelease(iterator); if (masterPort) mach_port_deallocate(mach_task_self(), masterPort); return err; }
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; } // Should only be one IOKit object for this volume. (And we only want one.) obj = IOIteratorNext(services); if (!obj) { result = 4; goto finish; } // we have the IOMedia for the partition. 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; /* We'll never loop forever. */ } while ( (service = IOIteratorNext(parents)) != 0 ) { kret = IORegistryEntryGetParentIterator (service, kIOServicePlane, &grandparents); IOObjectRelease(service); service = MACH_PORT_NULL; if (kret) { result = 6; goto finish; /* We'll never loop forever. */ } 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') { // nothing found 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; }
/**************************************************************************** * darwin_getTOC: get the TOC ****************************************************************************/ static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev ) { mach_port_t port; char *psz_devname; kern_return_t ret; CDTOC *pTOC = NULL; io_iterator_t iterator; io_registry_entry_t service; CFMutableDictionaryRef properties; CFDataRef data; /* get the device name */ if( ( psz_devname = strrchr( p_vcddev->psz_dev, '/') ) != NULL ) ++psz_devname; else psz_devname = p_vcddev->psz_dev; /* unraw the device name */ if( *psz_devname == 'r' ) ++psz_devname; /* get port for IOKit communication */ if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOMasterPort: 0x%08x", ret ); return( NULL ); } /* get service iterator for the device */ if( ( ret = IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, psz_devname ), &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IOServiceGetMatchingServices: 0x%08x", ret ); return( NULL ); } /* first service */ service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); /* search for kIOCDMediaClass */ while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) ) { if( ( ret = IORegistryEntryGetParentIterator( service, kIOServicePlane, &iterator ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryGetParentIterator: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } IOObjectRelease( service ); service = IOIteratorNext( iterator ); IOObjectRelease( iterator ); } if( !service ) { msg_Err( p_this, "search for kIOCDMediaClass came up empty" ); return( NULL ); } /* create a CF dictionary containing the TOC */ if( ( ret = IORegistryEntryCreateCFProperties( service, &properties, kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS ) { msg_Err( p_this, "IORegistryEntryCreateCFProperties: 0x%08x", ret ); IOObjectRelease( service ); return( NULL ); } /* get the TOC from the dictionary */ if( ( data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) ) ) != NULL ) { CFRange range; CFIndex buf_len; buf_len = CFDataGetLength( data ) + 1; range = CFRangeMake( 0, buf_len ); if( ( pTOC = malloc( buf_len ) ) != NULL ) { CFDataGetBytes( data, range, (u_char *)pTOC ); } } else { msg_Err( p_this, "CFDictionaryGetValue failed" ); } CFRelease( properties ); IOObjectRelease( service ); return( pTOC ); }