DADissenterRef BlockMount(DADiskRef disk, void *context) { CFDictionaryRef description = DADiskCopyDescription(disk); CFStringRef name = description ? CFDictionaryGetValue(description, kDADiskDescriptionVolumeNameKey) : NULL; DADissenterRef dissenter = NULL; bool block = false; char *str = NULL; if (name) { int i; CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8); str = alloca(length + 1); CFStringGetCString(name, str, length, kCFStringEncodingUTF8); for (i = 0; i < nameCount; i++) { if (CFEqual(name, names[i])) { block = true; break; } } } if (block) { dissenter = DADissenterCreate(kCFAllocatorDefault, kDAReturnNotPermitted, NULL); if(!quiet) if(!quiet) fprintf(stderr, "BLOCKED volume `%s'\n", str); } else { if(!quiet) if(!quiet) fprintf(stderr, "allowed volume `%s'\n", str); } if (description) { CFRelease(description); } return dissenter; }
static void disk_appeared_cb(DADiskRef disk, void *ctx) { CFDictionaryRef description = NULL; CFBooleanRef mountable; CFStringRef content = NULL; if (!ctx || !disk) return; description = DADiskCopyDescription(disk); if (!description) return; mountable = CFDictionaryGetValue(description, kDADiskDescriptionVolumeMountableKey); if (!mountable) goto out; content = CFDictionaryGetValue(description, kDADiskDescriptionMediaContentKey); if (!content) goto out; if (CFBooleanGetValue(mountable) && CFStringCompare(content, CFSTR("53746F72-6167-11AA-AA11-00306543ECAC"), kCFCompareCaseInsensitive) != kCFCompareEqualTo && CFStringCompare(content, CFSTR("426F6F74-0000-11AA-AA11-00306543ECAC"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) { /* The disk is marked mountable and isn't CoreStorage or Apple_Boot, * which means that it actually is mountable (since we lie and mark * CoreStorage disks as mountable). */ *((bool *)ctx) = true; } out: if (description) CFRelease(description); }
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 }
void DiskArbitrationEventPublisher::DiskAppearedCallback(DADiskRef disk, void* context) { auto ec = createEventContext(); CFDictionaryRef disk_properties = DADiskCopyDescription(disk); CFTypeRef devicePathKey; if (!CFDictionaryGetValueIfPresent( disk_properties, kDADiskDescriptionDevicePathKey, &devicePathKey)) { CFRelease(disk_properties); return; } auto device_path = stringFromCFString((CFStringRef)devicePathKey); ec->device_path = device_path; auto entry = IORegistryEntryFromPath(kIOMasterPortDefault, device_path.c_str()); if (entry == MACH_PORT_NULL) { CFRelease(disk_properties); return; } auto protocol_properties = (CFDictionaryRef)IORegistryEntryCreateCFProperty( entry, CFSTR(kIOPropertyProtocolCharacteristicsKey_), kCFAllocatorDefault, kNilOptions); if (protocol_properties != nullptr) { CFDataRef path = (CFDataRef)CFDictionaryGetValue( protocol_properties, CFSTR(kVirtualInterfaceLocation_)); if (path != nullptr) { ec->path = stringFromCFData(path); // extract checksum once on the whole disk and not for every partition if (CFBooleanGetValue((CFBooleanRef)CFDictionaryGetValue( disk_properties, kDADiskDescriptionMediaWholeKey))) { ec->checksum = extractUdifChecksum(ec->path); } } else { // There was no interface location. ec->path = getProperty(kDADiskDescriptionDevicePathKey, disk_properties); } CFRelease(protocol_properties); } else { ec->path = ""; } if (ec->path.find("/SSD0@0") == std::string::npos) { // This is not an internal SSD. fire("add", ec, disk_properties); } CFRelease(disk_properties); IOObjectRelease(entry); }
static void scan_disk_appeared_cb(DADiskRef disk, void *c) { struct scan_context *context = (struct scan_context *) c; int ix = context->count; if (ix < context->max_devices) { sprintf(context->devices[ix].path, "/dev/r%s", DADiskGetBSDName(disk)); CFDictionaryRef info = DADiskCopyDescription(disk); CFNumberRef cfsize = CFDictionaryGetValue(info, kDADiskDescriptionMediaSizeKey); int64_t size; CFNumberGetValue(cfsize, kCFNumberSInt64Type, &size); context->devices[ix].size = size; CFRelease(info); context->count++; } }
/* * 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); }
void diskChangedCallback(DADiskRef disk, CFArrayRef keys, void *context) { if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), kDADiskDescriptionVolumeNameKey)) { const char *BSDname = DADiskGetBSDName(disk); CFDictionaryRef details = DADiskCopyDescription(disk); char *volName = getVolName(details); LOG(VB_MEDIA, LOG_INFO, QString("Disk %1 - changed name to '%2'.") .arg(BSDname).arg(volName)); reinterpret_cast<MonitorThreadDarwin *>(context) ->diskRename(BSDname, volName); CFRelease(details); free(volName); } }
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 }
static bool weLikeTheDisk(DADiskRef disk) { CFDictionaryRef description = NULL; CFStringRef protocol = NULL; bool ret = false; /* We will create an ExternalMedia assertion if any of these disks are present. That will prevent deep sleep. USB hard drive : Protocol = USB USB thumb drive : Protocol = USB SD Card : Protocol = USB, Protocol = Secure Digital External drive : Interconnect Location = External These disks do not cause us to create an ExternalMedia assertion; CD/DVD : Protocol = ATAPI Disk Image : Protocol = Disk Image */ description = DADiskCopyDescription(disk); if (description) { if (CFDictionaryGetValue(description, kDADiskDescriptionDeviceInternalKey) == kCFBooleanFalse) { ret = true; } else { protocol = CFDictionaryGetValue(description, kDADiskDescriptionDeviceProtocolKey); if (protocol && (CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeUSB)) || CFEqual(protocol, CFSTR(kIOPropertyPhysicalInterconnectTypeSecureDigital)))) { ret = true; } } CFRelease(description); } return ret; }
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); }
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 }
void diskAppearedCallback(DADiskRef disk, void *context) { const char *BSDname = DADiskGetBSDName(disk); CFDictionaryRef details; bool isCDorDVD; MythMediaType mediaType; QString model; MonitorThreadDarwin *mtd; QString msg = "diskAppearedCallback() - "; char *volName; if (!BSDname) { LOG(VB_MEDIA, LOG_INFO, msg + "Skipping non-local device"); return; } if (!context) { LOG(VB_GENERAL, LOG_ALERT, msg + "Error. Invoked with a NULL context."); return; } mtd = reinterpret_cast<MonitorThreadDarwin*>(context); // We want to monitor CDs/DVDs and USB cameras or flash drives, // but probably not hard disk or network drives. For now, ignore // any disk or partitions that are not on removable media. // Seems OK for hot-plug USB/FireWire disks (i.e. they are removable) details = DADiskCopyDescription(disk); if (kCFBooleanFalse == CFDictionaryGetValue(details, kDADiskDescriptionMediaRemovableKey)) { LOG(VB_MEDIA, LOG_INFO, msg + QString("Skipping non-removable %1") .arg(BSDname)); CFRelease(details); return; } // Get the volume and model name for more user-friendly interaction volName = getVolName(details); if (!volName) { LOG(VB_MEDIA, LOG_INFO, msg + QString("No volume name for dev %1") .arg(BSDname)); CFRelease(details); return; } model = getModel(details); mediaType = MediaTypeForBSDName(BSDname); isCDorDVD = (mediaType == MEDIATYPE_DVD) || (mediaType == MEDIATYPE_AUDIO); // We know it is removable, and have guessed the type. // Call a helper function to create appropriate objects and insert LOG(VB_MEDIA, LOG_INFO, QString("Found disk %1 - volume name '%2'.") .arg(BSDname).arg(volName)); mtd->diskInsert(BSDname, volName, model, isCDorDVD); CFRelease(details); free(volName); }
__private_extern__ DAReturn _DAAuthorize( DASessionRef session, _DAAuthorizeOptions options, DADiskRef disk, const char * right ) { DAReturn status; status = kDAReturnNotPrivileged; if ( status ) { if ( ( options & _kDAAuthorizeOptionIsOwner ) ) { uid_t diskUID; status = _DAServerDiskGetUserUID( _DADiskGetSessionID( disk ), _DADiskGetID( disk ), &diskUID ); if ( status ) { return status; } status = kDAReturnNotPrivileged; if ( diskUID == geteuid( ) ) { status = kDAReturnSuccess; } } } if ( status ) { AuthorizationRef authorization; authorization = _DASessionGetAuthorization( session ); if ( authorization ) { CFDictionaryRef description; description = DADiskCopyDescription( disk ); if ( description ) { AuthorizationFlags flags; AuthorizationItem item; char * name; AuthorizationRights rights; flags = kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize; { CFTypeRef object; object = CFDictionaryGetValue( description, kDADiskDescriptionDeviceProtocolKey ); if ( object && CFEqual( object, CFSTR( kIOPropertyPhysicalInterconnectTypeVirtual ) ) ) { asprintf( &name, "system.volume.virtual.%s", right ); } else { if ( CFDictionaryGetValue( description, kDADiskDescriptionMediaRemovableKey ) == kCFBooleanTrue ) { asprintf( &name, "system.volume.removable.%s", right ); } else { if ( CFDictionaryGetValue( description, kDADiskDescriptionDeviceInternalKey ) == kCFBooleanTrue ) { asprintf( &name, "system.volume.internal.%s", right ); } else { asprintf( &name, "system.volume.external.%s", right ); } } } } if ( name ) { item.flags = 0; item.name = name; item.value = NULL; item.valueLength = 0; rights.count = 1; rights.items = &item; status = AuthorizationCopyRights( authorization, &rights, NULL, flags, NULL ); if ( status ) { status = kDAReturnNotPrivileged; } free( name ); } CFRelease( description ); } } } return status; }
// 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; }
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; }
void DiskArbitrationEventPublisher::DiskDisappearedCallback(DADiskRef disk, void* context) { CFDictionaryRef disk_properties = DADiskCopyDescription(disk); fire("remove", createEventContext(), disk_properties); CFRelease(disk_properties); }
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); }