Example #1
0
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;
}
Example #2
0
/**
 * 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;
}
Example #3
0
/*
 * 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);
}
Example #4
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;
}
Example #5
0
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);
}
Example #6
0
// 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;
}
Example #7
0
/*
 * 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;
}
Example #8
0
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);
      }
    }
  }
}
Example #9
0
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 */
Example #10
0
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;
}
Example #11
0
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;
}
Example #19
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;
}
Example #20
0
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;
}
Example #22
0
File: cdrom.c Project: Geal/vlc
/****************************************************************************
 * 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 );
}