Re: NSOpenPanel & NSFileTypeForHFSTypeCode
Re: NSOpenPanel & NSFileTypeForHFSTypeCode
- Subject: Re: NSOpenPanel & NSFileTypeForHFSTypeCode
- From: Steve Checkoway <email@hidden>
- Date: Wed, 10 Oct 2007 20:11:30 -0700
On Oct 10, 2007, at 2:18 PM, Chris Heimark wrote:
I am going to qualify the list of usable volumes for my application
using NSTask running diskutil and filtering ONLY for the volumes I
want - which in my case are USB mounted flash drives. So I may just
end up with a NSPopupButton selector filled with only qualified
volumes. So '/' will not be one of them...
It's possible to use the IOKit to find mounted flash drives so you
wouldn't have to use diskutil. I don't know if this is something that
would be worth doing in your case (since I don't know what your case
is) since it's not obvious how to do such things. See <http://lists.apple.com/archives/usb/2002/Jan/msg00003.html
>.
What I ended up doing in this case was use getfsstat and iterate over
the mounted file systems looking for those with f_mntfromname that
starts with /dev and then use the IOKit to check if it is a mass
storage device.
I don't claim this to be the best way to do this, but I found no
example code. Here's some code (missing a bit of error checking) that
seems to work.
[dualg5:~/temp] steve$ cat usb.c
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/storage/IOMedia.h>
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <paths.h>
#include <libgen.h>
int main()
{
int num = getfsstat( NULL, 0, MNT_NOWAIT );
struct statfs *fs = malloc( num*sizeof(struct statfs) );
num = getfsstat( fs, num*sizeof(struct statfs), MNT_NOWAIT );
int i;
for( i = 0; i < num; ++i )
{
if( strncmp(fs[i].f_mntfromname, _PATH_DEV, strlen(_PATH_DEV)) )
continue;
char *disk = basename( fs[i].f_mntfromname );
CFMutableDictionaryRef dict =
IOBSDNameMatching( kIOMasterPortDefault, 0, disk );
if( dict == NULL )
continue;
CFDictionarySetValue( dict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue );
CFDictionarySetValue( dict, CFSTR(kIOMediaEjectableKey),
kCFBooleanTrue );
CFDictionarySetValue( dict, CFSTR(kIOMediaWritableKey),
kCFBooleanTrue );
io_iterator_t iter;
// This consumes a reference to the dictionary so don't CFRelease()
it.
kern_return_t ret =
IOServiceGetMatchingServices( kIOMasterPortDefault, dict, &iter );
if( ret != KERN_SUCCESS || iter == 0 )
continue;
io_registry_entry_t entry;
while( (entry = IOIteratorNext(iter)) )
{
io_string_t path;
ret = IORegistryEntryGetPath( entry, kIOServicePlane, path );
IOObjectRelease( entry );
if( ret != KERN_SUCCESS )
continue;
char *p = strstr( path, "/IOUSBMassStorageClass" );
if( p == NULL )
continue;
// This is probably not the right way to do this, but it seems to
work.
*(p-1) = '\0';
p = strrchr( path, '/' );
if( p == NULL )
continue;
*p = '\0';
io_registry_entry_t device =
IORegistryEntryFromPath( kIOMasterPortDefault, path );
if( device == MACH_PORT_NULL )
continue;
puts( fs[i].f_mntonname );
// You can get information about the USB device using device
// with IORegistryEntryCreateCFProperty().
IOObjectRelease( device );
// I'm not sure that this iterator will have multiple entries
// ever but one seems like enough.
break;
}
IOObjectRelease( iter );
}
free( fs );
return 0;
}
[dualg5:~/temp] steve$ gcc -Wall usb.c -framework CoreFoundation -
framework IOKit
[dualg5:~/temp] steve$ ./a.out
[dualg5:~/temp] steve$ ./a.out
/Volumes/NO NAME
[dualg5:~/temp] steve$ ./a.out
/Volumes/NO NAME
/Volumes/Secure II
The first had no drives plugged in, the second had one drive, and the
third had two drives.
Hope this helps.
--
Steve Checkoway
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden