/** * Use the DiskArbitration Daemon to inform us of media changes */ void MonitorThreadDarwin::run(void) { CFDictionaryRef match = kDADiskDescriptionMatchVolumeMountable; DASessionRef daSession = DASessionCreate(kCFAllocatorDefault); IOMasterPort(MACH_PORT_NULL, &sMasterPort); DARegisterDiskAppearedCallback(daSession, match, diskAppearedCallback, this); DARegisterDiskDisappearedCallback(daSession, match, diskDisappearedCallback, this); DARegisterDiskDescriptionChangedCallback(daSession, match, kDADiskDescriptionWatchVolumeName, diskChangedCallback, this); DASessionScheduleWithRunLoop(daSession, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // Nice and simple, as long as our monitor is valid and active, // loop and let daSession check the devices. while (m_Monitor && m_Monitor->IsActive()) { // Run the run loop for interval (milliseconds) - this will // handle any disk arbitration appeared/dissappeared events CFRunLoopRunInMode(kCFRunLoopDefaultMode, (float) m_Interval / 1000.0f, false ); } DAUnregisterCallback(daSession, (void(*))diskChangedCallback, this); DAUnregisterCallback(daSession, (void(*))diskDisappearedCallback, this); DAUnregisterCallback(daSession, (void(*))diskAppearedCallback, this); CFRelease(daSession); }
static int iokit_unmount (MMCDEV *mmc) { if (0 == mmc->is_mounted) { return 0; /* nothing to do */ } BD_DEBUG(DBG_MMC, "Unmounting disk\n"); mmc->session = DASessionCreate (kCFAllocatorDefault); if (NULL == mmc->session) { BD_DEBUG(DBG_MMC, "Could not create a disc arbitration session\n"); return -1; } mmc->disk = DADiskCreateFromBSDName (kCFAllocatorDefault, mmc->session, mmc->bsd_name); if (NULL == mmc->disk) { BD_DEBUG(DBG_MMC, "Could not create a disc arbitration disc for the device\n"); CFRelease (mmc->session); mmc->session = NULL; return -1; } DAApprovalSessionScheduleWithRunLoop (mmc->session, CFRunLoopGetCurrent (), kCFRunLoopDefaultMode); DADiskUnmount (mmc->disk, kDADiskUnmountOptionForce, iokit_unmount_complete, mmc); CFRunLoopRunInMode (kCFRunLoopDefaultMode, 10, true); return mmc->is_mounted ? -1 : 0; }
int diskarb_unmount( const char * dir, int flags ) { int status; status = -1; if ( dir ) { DASessionRef session; session = DASessionCreate( kCFAllocatorDefault ); if ( session ) { CFURLRef path; path = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, ( void * ) dir, strlen( dir ), TRUE ); if ( path ) { DADiskRef disk; disk = DADiskCreateFromVolumePath( kCFAllocatorDefault, session, path ); if ( disk ) { DADiskUnmountOptions options; options = kDADiskUnmountOptionDefault; if ( ( flags & MNT_FORCE ) ) { options |= kDADiskUnmountOptionForce; } DASessionScheduleWithRunLoop( session, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode ); DADiskUnmount( disk, options, __diskarb_unmount, &status ); if ( status == -1 ) { CFRunLoopRun( ); } status = status ? -1 : 0; DASessionUnscheduleFromRunLoop( session, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode ); CFRelease( disk ); } CFRelease( path ); } CFRelease( session ); } } return status; }
DiskArbitrationDispatcher::DiskArbitrationDispatcher() : m_impl(new Impl) { m_impl->session = DASessionCreate(kCFAllocatorDefault); DARegisterDiskAppearedCallback(m_impl->session, nullptr, [](DADiskRef disk, void * ctx) { static_cast<DiskArbitrationDispatcher*>(ctx)->diskAppeared(disk); }, this); DARegisterDiskDisappearedCallback(m_impl->session, nullptr, [](DADiskRef disk, void * ctx) { static_cast<DiskArbitrationDispatcher*>(ctx)->diskDisappeared(disk); }, this); }
void CDarwinStorageProvider::GetRemovableDrives(VECSOURCES &removableDrives) { #if defined(TARGET_DARWIN_OSX) if (CDarwinUtils::IsLion()) return; //temp workaround for crash in Cocoa_GetVolumeNameFromMountPoint on 10.7.x DASessionRef session = DASessionCreate(kCFAllocatorDefault); if (session) { unsigned i, count = 0; struct statfs *buf = NULL; std::string mountpoint, devicepath; count = getmntinfo(&buf, 0); for (i=0; i<count; i++) { mountpoint = buf[i].f_mntonname; devicepath = buf[i].f_mntfromname; DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devicepath.c_str()); if (disk) { CFDictionaryRef details = DADiskCopyDescription(disk); if (details) { if (kCFBooleanTrue == CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey)) { CMediaSource share; share.strPath = mountpoint; Cocoa_GetVolumeNameFromMountPoint(mountpoint.c_str(), share.strName); share.m_ignore = true; // detect if its a cd or dvd // needs to be ejectable if (kCFBooleanTrue == CFDictionaryGetValue(details, kDADiskDescriptionMediaEjectableKey)) { CFStringRef mediaKind = (CFStringRef)CFDictionaryGetValue(details, kDADiskDescriptionMediaKindKey); // and either cd or dvd kind of media in it if (mediaKind != NULL && (CFStringCompare(mediaKind, CFSTR(kIOCDMediaClass), 0) == kCFCompareEqualTo || CFStringCompare(mediaKind, CFSTR(kIODVDMediaClass), 0) == kCFCompareEqualTo)) share.m_iDriveType = CMediaSource::SOURCE_TYPE_DVD; } removableDrives.push_back(share); } CFRelease(details); } CFRelease(disk); } } CFRelease(session); } #endif }
bool QDeviceWatcherPrivate::init() { //get sDevices //FSGetVolumeInfo() mSession = DASessionCreate(kCFAllocatorDefault); DARegisterDiskAppearedCallback(mSession, NULL, onDiskAppear, this); DARegisterDiskDisappearedCallback(mSession, NULL, onDiskDisappear, this); }
__private_extern__ void ExternalMedia_prime(void) { gExternalMediaSet = CFSetCreateMutable(0, 0, &kCFTypeSetCallBacks); if (!gExternalMediaSet) return; gDASession = DASessionCreate(0); DARegisterDiskAppearedCallback(gDASession, kDADiskDescriptionMatchVolumeMountable, _DiskAppeared, NULL); DARegisterDiskDisappearedCallback(gDASession, kDADiskDescriptionMatchVolumeMountable, _DiskDisappeared, NULL); DASessionScheduleWithRunLoop(gDASession, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); }
/* * Check if there are any mountable partitions on the disk. If there are any * mountable partitions, then we don't want to display the dialog. CoreStorage * and Apple_Boot partitions don't count as mountable for our purposes. */ static bool check_all_partitions(char *devname) { bool found_mountable_fs = false; SInt32 rc; CFNumberRef num = NULL; CFDictionaryRef description = NULL, matchDict = NULL; DASessionRef session = (DASessionRef)0; DADiskRef disk = (DADiskRef)0; session = DASessionCreate(kCFAllocatorDefault); if (session == (DASessionRef)0) goto exit; disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devname); if (disk == (DADiskRef)0) goto exit; description = DADiskCopyDescription(disk); num = CFDictionaryGetValue(description, kDADiskDescriptionMediaBSDUnitKey); matchDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kDADiskDescriptionMediaBSDUnitKey, (const void **)&num, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); DARegisterIdleCallback(session, idle_cb, &found_mountable_fs); DARegisterDiskAppearedCallback(session, matchDict, disk_appeared_cb, &found_mountable_fs); rc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); DAUnregisterCallback(session, idle_cb, &found_mountable_fs); DAUnregisterCallback(session, disk_appeared_cb, &found_mountable_fs); DASessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); exit: if (disk) CFRelease(disk); if (session) CFRelease(session); if (description) CFRelease(description); if (matchDict) CFRelease(matchDict); return (!found_mountable_fs); }
QString DeviceInfo::deviceId() const { QString uuid; DADiskRef disk; CFDictionaryRef descDict; DASessionRef session = DASessionCreate(NULL); if (session) { const char *mountPoint = "/"; CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)mountPoint, strlen(mountPoint), TRUE); disk = DADiskCreateFromVolumePath(NULL, session, url); CFRelease(url); if (disk) { descDict = DADiskCopyDescription(disk); if (descDict) { CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(descDict, CFSTR("DAVolumeUUID")); CFStringRef strValue = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), value); uuid = QString::fromCFString(strValue); CFRelease(strValue); CFRelease(descDict); } CFRelease(disk); } CFRelease(session); } QCryptographicHash hash(QCryptographicHash::Sha224); hash.addData(uuid.toLatin1()); return QString::fromLatin1(hash.result().toHex()); }
void CDarwinStorageProvider::GetRemovableDrives(VECSOURCES &removableDrives) { #if defined(TARGET_DARWIN_OSX) DASessionRef session = DASessionCreate(kCFAllocatorDefault); if (session) { unsigned i, count = 0; struct statfs *buf = NULL; std::string mountpoint, devicepath; count = getmntinfo(&buf, 0); for (i=0; i<count; i++) { mountpoint = buf[i].f_mntonname; devicepath = buf[i].f_mntfromname; DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devicepath.c_str()); if (disk) { CFDictionaryRef details = DADiskCopyDescription(disk); if (details) { if (kCFBooleanTrue == CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey)) { CMediaSource share; share.strPath = mountpoint; Cocoa_GetVolumeNameFromMountPoint(mountpoint.c_str(), share.strName); share.m_ignore = true; removableDrives.push_back(share); } CFRelease(details); } CFRelease(disk); } } CFRelease(session); } #endif }
void DiskArbitrationEventPublisher::restart() { if (run_loop_ == nullptr) { return; } stop(); WriteLock lock(mutex_); session_ = DASessionCreate(kCFAllocatorDefault); DARegisterDiskAppearedCallback( session_, nullptr, DiskArbitrationEventPublisher::DiskAppearedCallback, nullptr); DARegisterDiskDisappearedCallback( session_, nullptr, DiskArbitrationEventPublisher::DiskDisappearedCallback, nullptr); DASessionScheduleWithRunLoop(session_, run_loop_, kCFRunLoopDefaultMode); }
int main(int argc, char **argv) { int ret = -1; DASessionRef session = NULL; DADiskRef disk = NULL; CFDictionaryRef diskInfo = NULL; char *diskName = DEFAULT_DISK_NAME; // create a new Disk Arbitration session session = DASessionCreate(kCFAllocatorDefault); OUT_ON_NULL(session, "failed to create Disk Arbitration session"); if (argc == 2) diskName = argv[1]; // create a new disk object from the given BSD device name disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, diskName); OUT_ON_NULL(disk, "failed to create disk object"); // obtain disk's description diskInfo = DADiskCopyDescription(disk); OUT_ON_NULL(diskInfo, "failed to retrieve disk description"); ret = printDictionaryAsXML(diskInfo); out: if (diskInfo) CFRelease(diskInfo); if (disk) CFRelease(disk); if (session) CFRelease(session); exit(ret); }
/* * Tell Disk Arbitration not to try to mount the disk. */ static void suppress_mount(char *devname) { DASessionRef session = (DASessionRef)0; DADiskRef disk = (DADiskRef)0; session = DASessionCreate(kCFAllocatorDefault); if (session == (DASessionRef)0) goto exit; disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devname); if (disk == (DADiskRef)0) goto exit; /* Tell DA not to auto-mount this disk (since we're lying about it being * mountable in the first place). */ DADiskSetOptions(disk, kDADiskOptionMountAutomatic, FALSE); exit: if (disk) CFRelease(disk); if (session) CFRelease(session); }
/** * Initialize mmc support */ void mmc_init() { da_session = DASessionCreate(kCFAllocatorDefault); DASessionScheduleWithRunLoop(da_session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); }
void CDarwinStorageProvider::GetLocalDrives(VECSOURCES &localDrives) { CMediaSource share; // User home folder #ifdef TARGET_DARWIN_IOS share.strPath = "special://envhome/"; #else share.strPath = getenv("HOME"); #endif share.strName = g_localizeStrings.Get(21440); share.m_ignore = true; localDrives.push_back(share); #if defined(TARGET_DARWIN_IOS) // iOS Inbox folder share.strPath = "special://envhome/Documents/Inbox"; share.strName = "Inbox"; share.m_ignore = true; localDrives.push_back(share); #endif #if defined(TARGET_DARWIN_OSX) // User desktop folder share.strPath = getenv("HOME"); share.strPath += "/Desktop"; share.strName = "Desktop"; share.m_ignore = true; localDrives.push_back(share); // Volumes (all mounts are present here) share.strPath = "/Volumes"; share.strName = "Volumes"; share.m_ignore = true; localDrives.push_back(share); // This will pick up all local non-removable disks including the Root Disk. DASessionRef session = DASessionCreate(kCFAllocatorDefault); if (session) { unsigned i, count = 0; struct statfs *buf = NULL; std::string mountpoint, devicepath; count = getmntinfo(&buf, 0); for (i=0; i<count; i++) { mountpoint = buf[i].f_mntonname; devicepath = buf[i].f_mntfromname; DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, devicepath.c_str()); if (disk) { CFDictionaryRef details = DADiskCopyDescription(disk); if (details) { if (kCFBooleanFalse == CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey)) { CMediaSource share; share.strPath = mountpoint; Cocoa_GetVolumeNameFromMountPoint(mountpoint.c_str(), share.strName); share.m_ignore = true; localDrives.push_back(share); } CFRelease(details); } CFRelease(disk); } } CFRelease(session); } #endif }
static int updateAppleBootIfPresent(BLContextPtr context, char *device, CFDataRef bootxData, CFDataRef labelData) { char booterDev[MAXPATHLEN]; io_service_t service = 0; CFStringRef name = NULL; int32_t needsBooter = 0; int32_t isBooter = 0; BLUpdateBooterFileSpec *spec = NULL; int32_t specCount = 0, currentCount = 0; int ret; strlcpy(booterDev, "/dev/", sizeof booterDev); ret = BLDeviceNeedsBooter(context, device, &needsBooter, &isBooter, &service); if(ret) { blesscontextprintf(context, kBLLogLevelError, "Could not determine if partition needs booter\n" ); return 1; } if(!(needsBooter || isBooter)) return 0; for(;;) { char label[MAXPATHLEN]; #if USE_DISKARBITRATION DADiskRef disk = NULL; DASessionRef session = NULL; CFDictionaryRef props = NULL; CFStringRef daName = NULL; if(labelData) break; // no need to generate session = DASessionCreate(kCFAllocatorDefault); if(session == NULL) { blesscontextprintf(context, kBLLogLevelVerbose, "Can't connect to DiskArb\n"); break; } disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, device+5); if(disk == NULL) { CFRelease(session); blesscontextprintf(context, kBLLogLevelVerbose, "Can't create DADisk for %s\n", device + 5); break; } props = DADiskCopyDescription(disk); if(props == NULL) { CFRelease(session); CFRelease(disk); blesscontextprintf(context, kBLLogLevelVerbose, "Can't get properties for %s\n", device + 5); break; } daName = CFDictionaryGetValue(props, kDADiskDescriptionVolumeNameKey); if(daName == NULL) { CFRelease(props); CFRelease(disk); CFRelease(session); blesscontextprintf(context, kBLLogLevelVerbose, "Can't get properties for %s\n", device + 5); break; } if(!CFStringGetCString(daName, label, sizeof(label), kCFStringEncodingUTF8)) { CFRelease(props); CFRelease(disk); CFRelease(session); break; } CFRelease(props); CFRelease(disk); CFRelease(session); #else // !USE_DISKARBITRATION strlcpy(label, "Unknown", sizeof(label)); #endif // !USE_DISKARBITRATION ret = BLGenerateLabelData(context, label, kBitmapScale_1x, &labelData); if(ret) labelData = NULL; break; } if(!(bootxData || labelData)) { IOObjectRelease(service); return 0; } name = IORegistryEntryCreateCFProperty( service, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0); if(name == NULL || CFStringGetTypeID() != CFGetTypeID(name)) { IOObjectRelease(service); blesscontextprintf(context, kBLLogLevelError, "Could not find bsd name for %x\n" , service); return 2; } IOObjectRelease(service); service = 0; if(!CFStringGetCString(name,booterDev+5,sizeof(booterDev)-5,kCFStringEncodingUTF8)) { CFRelease(name); blesscontextprintf(context, kBLLogLevelError, "Could not find bsd name for %x\n" , service); return 3; } CFRelease(name); if(labelData) specCount += 2; if(bootxData) specCount += 1; spec = calloc(specCount, sizeof(spec[0])); if(labelData) { spec[currentCount+0].version = 0; spec[currentCount+0].reqType = kBL_OSTYPE_PPC_TYPE_OFLABEL; spec[currentCount+0].reqCreator = kBL_OSTYPE_PPC_CREATOR_CHRP; spec[currentCount+0].reqParentDir = 0; spec[currentCount+0].reqFilename = NULL; spec[currentCount+0].payloadData = labelData; spec[currentCount+0].postType = 0; // no type spec[currentCount+0].postCreator = 0; // no type spec[currentCount+0].foundFile = 0; spec[currentCount+0].updatedFile = 0; spec[currentCount+1].version = 0; spec[currentCount+1].reqType = kBL_OSTYPE_PPC_TYPE_OFLABEL_PLACEHOLDER; spec[currentCount+1].reqCreator = kBL_OSTYPE_PPC_CREATOR_CHRP; spec[currentCount+1].reqParentDir = 0; spec[currentCount+1].reqFilename = NULL; spec[currentCount+1].payloadData = labelData; spec[currentCount+1].postType = kBL_OSTYPE_PPC_TYPE_OFLABEL; spec[currentCount+1].postCreator = 0; // no type spec[currentCount+1].foundFile = 0; spec[currentCount+1].updatedFile = 0; currentCount += 2; } if(bootxData) { spec[currentCount+0].version = 0; spec[currentCount+0].reqType = kBL_OSTYPE_PPC_TYPE_BOOTX; spec[currentCount+0].reqCreator = kBL_OSTYPE_PPC_CREATOR_CHRP; spec[currentCount+0].reqParentDir = 0; spec[currentCount+0].reqFilename = NULL; spec[currentCount+0].payloadData = bootxData; spec[currentCount+0].postType = 0; // no type spec[currentCount+0].postCreator = 0; // no type spec[currentCount+0].foundFile = 0; spec[currentCount+0].updatedFile = 0; } ret = BLUpdateBooter(context, booterDev, spec, specCount); if(ret) { blesscontextprintf(context, kBLLogLevelError, "Error enumerating HFS+ volume\n"); return 1; } if(bootxData) { if(!(spec[currentCount].foundFile)) { blesscontextprintf(context, kBLLogLevelError, "No pre-existing BootX found in HFS+ volume\n"); return 2; } if(!(spec[currentCount].updatedFile)) { blesscontextprintf(context, kBLLogLevelError, "BootX was not updated\n"); return 3; } } if(labelData) { if(!(spec[0].foundFile || spec[1].foundFile)) { blesscontextprintf(context, kBLLogLevelError, "No pre-existing OF label found in HFS+ volume\n"); return 2; } if(!(spec[0].updatedFile || spec[1].updatedFile)) { blesscontextprintf(context, kBLLogLevelError, "OF label was not updated\n"); return 3; } } free(spec); return 0; }
// 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; }
void genIOMediaDevice(const io_service_t& device, std::vector<std::string>& whole_devices, QueryData& results) { Row r; // Get the device properties CFMutableDictionaryRef properties; IORegistryEntryCreateCFProperties( device, &properties, kCFAllocatorDefault, kNilOptions); r["uuid"] = getIOKitProperty(properties, "UUID"); r["name"] = "/dev/" + getIOKitProperty(properties, "BSD Name"); r["size"] = getIOKitProperty(properties, "Size"); auto type = getIOKitProperty(properties, "Whole"); if (type == "1") { // The "Whole" property applies to the entire disk entry, not partitions. whole_devices.push_back(r["name"]); } else { // Otherwise search the list of whole disks to find the node parent. for (const auto& parent : whole_devices) { if (r.at("name").find(parent) == 0) { r["parent"] = parent; } } } // This is the IOKit name, which is the device's label. io_name_t name; auto kr = IORegistryEntryGetName(device, name); if (kr == KERN_SUCCESS && (char*)name != nullptr) { r["label"] = std::string(name); } // Remaining details come from the Disk Arbitration service. DASessionRef session = DASessionCreate(kCFAllocatorDefault); CFDictionaryRef details; if (session != nullptr) { auto disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, session, device); if (disk != nullptr) { details = DADiskCopyDescription(disk); if (details != nullptr) { r["vendor"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceVendor"); r["model"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceModel"); r["type"] = getIOKitProperty((CFMutableDictionaryRef)details, "DADeviceProtocol"); CFRelease(details); } CFRelease(disk); } CFRelease(session); } results.push_back(r); CFRelease(properties); }