I would like to obtain a list of drives that are unmountable/ejectable using Cocoa/Objective-C under OS X.
I was hoping that NSWorkspace getFileSystemInfoForPath::::: would help me:
NSArray* listOfMedia = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths];
NSLog(@"%@", listOfMedia);
for (NSString* volumePath in listOfMedia)
{
BOOL isRemovable = NO;
BOOL isWritable = NO;
BOOL isUnmountable = NO;
NSString* description = [NSString string];
NSString* type = [NSString string];
BOOL result = [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:volumePath
isRemovable:&isRemovable
isWritable:&isWritable
isUnmountable:&isUnmountable
description:&description
type:&type];
NSLog(@"Result:%i Volume: %@, Removable:%i, W:%i, Unmountable:%i, Desc:%@, type:%@", result, volumePath, isRemovable, isWritable, isUnmountable, description, type);
}
Output:
...
Result:1 Volume: /Volumes/LR Photos, Removable:0, W:1, Unmountable:0, Desc:hfs, type:hfs
...
"LR Photos" is an external drive (connected via Thunderbolt) that should be removable and/or unmountable (or, at least I think it should be). :)
Should I be going about this a different way?
Thanks in advance!
You can use diskArbitration
framework.
#import <DiskArbitration/DiskArbitration.h>
+(NSMutableArray *)getListOfEjectableMedia
{
NSArray *mountedRemovableMedia = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
NSMutableArray *result = [NSMutableArray array];
for(NSURL *volURL in mountedRemovableMedia)
{
int err = 0;
DADiskRef disk;
DASessionRef session;
CFDictionaryRef descDict;
session = DASessionCreate(NULL);
if (session == NULL) {
err = EINVAL;
}
if (err == 0) {
disk = DADiskCreateFromVolumePath(NULL,session,(CFURLRef)volURL);
if (session == NULL) {
err = EINVAL;
}
}
if (err == 0) {
descDict = DADiskCopyDescription(disk);
if (descDict == NULL) {
err = EINVAL;
}
}
if (err == 0) {
CFTypeRef mediaEjectableKey = CFDictionaryGetValue(descDict,kDADiskDescriptionMediaEjectableKey);
CFTypeRef deviceProtocolName = CFDictionaryGetValue(descDict,kDADiskDescriptionDeviceProtocolKey);
if (mediaEjectableKey != NULL)
{
BOOL op = CFEqual(mediaEjectableKey, CFSTR("0")) || CFEqual(deviceProtocolName, CFSTR("USB"));
if (op) {
[result addObject:volURL];
}
}
}
if (descDict != NULL) {
CFRelease(descDict);
}
if (disk != NULL) {
CFRelease(disk);
}
if (session != NULL) {
CFRelease(session);
}
}
return result;
}
Update:
+ (NSMutableArray *)getListOfEjectableMedia {
NSArray *mountedRemovableMedia = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
NSMutableArray *result = [NSMutableArray array];
DASessionRef session = DASessionCreate(NULL); // Create the DASessionRef object outside the loop.
for (NSURL *volURL in mountedRemovableMedia) {
DADiskRef disk = DADiskCreateFromVolumePath(NULL, session, (__bridge CFURLRef)volURL); // Use the same session object for each disk.
if (disk != NULL) {
CFDictionaryRef descDict = DADiskCopyDescription(disk);
if (descDict != NULL) {
CFTypeRef mediaEjectableKey = CFDictionaryGetValue(descDict,kDADiskDescriptionMediaEjectableKey);
CFTypeRef deviceProtocolName = CFDictionaryGetValue(descDict,kDADiskDescriptionDeviceProtocolKey);
if (mediaEjectableKey != NULL) {
BOOL op = CFEqual(mediaEjectableKey, CFSTR("0")) || CFEqual(deviceProtocolName, CFSTR("USB"));
if (op) {
[result addObject:volURL];
}
}
CFRelease(descDict);
}
CFRelease(disk);
}
}
CFRelease(session); // Release the DASessionRef object after the loop.
return result;
}