get disk number(s) before getting bsdName - usb-flash-drive

I have just encountered one problem, I can get the bsdName with below code lines but if there are two partitions in a USB flash disk, then I can only get the last bsdName, can someone tell me how do I get all the bsdName from the USB drive? actually I would like to get the volume name of each partition... thanks in advance
CFStringRef bsdName = ( CFStringRef ) IORegistryEntrySearchCFProperty ( usbDevice,
kIOServicePlane,
CFSTR ( kIOBSDNameKey ),
kCFAllocatorDefault,
kIORegistryIterateRecursively );
NSLog(#"bsdName=%#",bsdName);
volumeName = deviceNameWithMountPath((NSString*)bsdName);
//find_hid_device(usbDevice);
NSLog(#"volume Name=%#",volumeName);
NSString *mediaType = FindWholeMedia(usbDevice);
NSLog(#"media type = %#",mediaType);
//CFRelease(bsdName);
// Done with this USB device; release the reference added by IOIteratorNext
kr = IOObjectRelease(usbDevice);
}
}
NSString *deviceNameWithMountPath(NSString *mountPath)
{
DASessionRef session = NULL;
DADiskRef disk = NULL;
CFDictionaryRef dd = NULL;
CFTypeRef val = nil;
session = DASessionCreate(kCFAllocatorDefault);
if (!session) {
NSLog(#"Can't create DiskArb session");
return nil;
}
// DASessionScheduleWithRunLoop(session,
// CFRunLoopGetCurrent(),
// kCFRunLoopDefaultMode);
//
// DARegisterDiskAppearedCallback(session, NULL, DiskAppeared, NULL);
disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, [mountPath UTF8String]);
if (!disk) {
NSLog(#"DADiskCreateFromBSDName(%s) failed", [mountPath UTF8String]);
return nil;
}
dd = DADiskCopyDescription(disk);
if (!dd) {
NSLog(#"DADiskCopyDescription(%s) failed", [mountPath UTF8String]);
return nil;
}
CFDictionaryGetValueIfPresent(dd, (kDADiskDescriptionVolumeNameKey), &val);
DiskAppeared(disk, NULL);
CFRelease(disk);
CFRelease(session);
return (NSString *)val;
}

Related

OS X Application How to get allocation blocks(cluster size) of a volume

I want to get size (in bytes) of allocation blocks of a removable volume.
In my Macos application, I use FSGetVolumeInfo method to get FSVolumeInfo object.
In FSVolumeInfo object, attribute "blockSize" is the right one.
However, method FSGetVolumeInfo is deprecated after Macos10.8.
Is there any function to replace?
Below is sample code with FSVolumeInfo :
const char* path = "/Volumes/Untitled";
FSCatalogInfo volCatalogInfo;
FSVolumeRefNum realVolRefNum;
FSVolumeInfo myVolumeinfo;
if ('\0' != path[0]) {
CFStringRef pathStr = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
CFURLRef volumePath = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStr, kCFURLPOSIXPathStyle, false);
FSRef volumeRef;
if (CFURLGetFSRef(volumePath, &volumeRef)) {
OSStatus err = FSGetCatalogInfo(&volumeRef, kFSCatInfoVolume, &volCatalogInfo, NULL, NULL, NULL);
if (noErr == err) {
FSVolumeRefNum volRefNum = volCatalogInfo.volume;
err = FSGetVolumeInfo(volRefNum, 0, &realVolRefNum, kFSVolInfoGettableInfo, &myVolumeinfo, NULL, NULL);
if (noErr == err) {
printf("get volume info success!");
}
}
}
}
I would look into standard c function calls I think, statvfs() does what you want.

Possible to programatically installed 'Untrusted Certificate' or 'P12' file in Keychain Access with 'Always Trust '?

I am new to the Keychain Access from mac.
I just have to installed Untrused Certificate or P12 file in keychain access programatically in Mac as 'Trust Always'.
I am using below code :
-(void)addCertificate
{
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:
#"/Users/Desktop/Certificates.p12"];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = (CFStringRef)#"";
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys,
values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
SecCertificateRef rootCert =
SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)
inPKCS12Data);
OSStatus securityError = SecPKCS12Import(inPKCS12Data,
optionsDictionary, &items);
if (securityError == 0) {
NSLog(#" *** Certificate install Success ***");
} else {
NSLog(#" *** Certificate install Failure ***");
}
OSStatus err = noErr;
CFTypeRef result;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassCertificate, kSecClass,
rootCert, kSecValueRef,
nil];
err = SecItemAdd((__bridge CFDictionaryRef)dict, &result);
if(err!=noErr) NSLog(#"error while importing");
if (err==errSecDuplicateItem) NSLog(#"Cert already installed");
NSLog(#":%i",(int)err);
assert(err==noErr||err==errSecDuplicateItem);
// accept no errors other than duplicate
err = noErr;
SecTrustRef trust;
err = SecTrustCreateWithCertificates(rootCert,
SecPolicyCreateBasicX509() ,&trust);
assert(err==noErr);
err = noErr;
CFMutableArrayRef newAnchorArray =
CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
CFArrayAppendValue(newAnchorArray,rootCert);
err = SecTrustSetAnchorCertificates(trust, newAnchorArray);
assert(err==noErr);
SecTrustResultType trustResult;
err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);
rootCert=nil; // Done with the policy object
}
By using this code we are adding certificate only
Please help me to out from this...

How to create certificate choosing window like one in Safari?

I was looking for a way to create a window like that one in my program, but I haven't found any implementation of that. All I can do for now is get all certificates from keychain, but I can't get a cert in pem or der format. It is needed to supply certificate to a particular site.
- (void)logMessageForStatus:(OSStatus)status
functionName:(NSString *)functionName
{
CFStringRef errorMessage;
errorMessage = SecCopyErrorMessageString(status, NULL);
NSLog(#"error after %#: %#", functionName, (__bridge NSString *)errorMessage);
CFRelease(errorMessage);
}
- (void)listCertificates
{
OSStatus status;
SecKeychainSearchRef search = NULL;
// The first argument being NULL indicates the user's current keychain list
status = SecKeychainSearchCreateFromAttributes(NULL,
kSecCertificateItemClass, NULL, &search);
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecKeychainSearchCreateFromAttributes()"];
return;
}
SecKeychainItemRef searchItem = NULL;
while (SecKeychainSearchCopyNext(search, &searchItem) != errSecItemNotFound) {
SecKeychainAttributeList attrList;
CSSM_DATA certData;
attrList.count = 0;
attrList.attr = NULL;
status = SecKeychainItemCopyContent(searchItem, NULL, &attrList,
(UInt32 *)(&certData.Length),
(void **)(&certData.Data));
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecKeychainItemCopyContent()"];
CFRelease(searchItem);
continue;
}
// At this point you should have a valid CSSM_DATA structure
// representing the certificate
SecCertificateRef certificate;
status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3,
CSSM_CERT_ENCODING_BER, &certificate);
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecCertificateCreateFromData()"];
SecKeychainItemFreeContent(&attrList, certData.Data);
CFRelease(searchItem);
continue;
}
// Do whatever you want to do with the certificate
// For instance, print its common name (if there's one)
CFStringRef commonName = NULL;
CFErrorRef err = NULL;
///CFArrayRef arr = NULL;
SecCertificateCopyCommonName(certificate, &commonName);
certs = SecCertificateCopyValues(certificate, NULL, &err);
//NSLog(#"common name = %#", (__bridge NSString *)commonName);
//NSLog(#"data = %#", (__bridge NSArray *)arr);
//certs = arr;
if (commonName) CFRelease(commonName);
//if (arr) CFRelease(arr);
SecKeychainItemFreeContent(&attrList, certData.Data);
CFRelease(searchItem);
}
CFRelease(search);
}
example
Is there any standard api to call such window? Or maybe there is some library? And how can I get der data from SecCertificateRef.
Thank you in advance!

Sqlite3 : "Database is locked" error

In my cocoa application I am maintaining a SQLite db within resources folder and trying to do some select, delete operations in it but after some time it starts giving me 'Database is locked' error.
The methods which I am using for select delete operations are as follows:
// method to retrieve data
if (sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK)
{
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
NSLog(#"mailBodyFor:%d andFlag:%d andFlag:%#",UId,x,Ffolder);
NSMutableArray *recordsToReturn = [[NSMutableArray alloc] initWithCapacity:2];
NSString *tempMsg;
const char *sqlStatementNew;
NSLog(#"before switch");
switch (x) {
case 9:
// tempMsg=[NSString stringWithFormat:#"SELECT * FROM users_messages"];
tempMsg=[NSString stringWithFormat:#"SELECT message,AttachFileOriName as oriFileName,AttachmentFileName as fileName FROM users_messages WHERE id = (select message_id from users_messages_status where id= '%d')",UId];
NSLog(#"mail body query - %#",tempMsg);
break;
default:
break;
}
sqlStatementNew = [tempMsg cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *compiledStatementNew;
NSLog(#"before if statement");
if(sqlite3_prepare_v2(database, sqlStatementNew, -1, &compiledStatementNew, NULL) == SQLITE_OK) {
NSLog(#"the sql is finalized");
while(sqlite3_step(compiledStatementNew) == SQLITE_ROW) {
NSMutableDictionary *recordDict = [[NSMutableDictionary alloc] initWithCapacity:3];
NSString *message;
if((char *)sqlite3_column_text(compiledStatementNew, 0)){
message = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatementNew, 0)];
}
else{
message = #"";
}
NSLog(#"message - %#",message);
NSString *oriFileName;
if((char *)sqlite3_column_text(compiledStatementNew, 1)){
oriFileName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatementNew, 1)];
}
else{
oriFileName = #"";
}
NSLog(#"oriFileName - %#",oriFileName);
NSString *fileName;
if((char *)sqlite3_column_text(compiledStatementNew, 2)){
fileName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatementNew, 2)];
}
else{
fileName = #"";
}
NSLog(#"fileName - %#",fileName);
[recordDict setObject:message forKey:#"message"];
[recordDict setObject:oriFileName forKey:#"oriFileName"];
[recordDict setObject:fileName forKey:#"fileName"];
[recordsToReturn addObject:recordDict];
[recordDict release];
}
sqlite3_finalize(compiledStatementNew);
sqlite3_close(database);
NSLog(#"user messages return -%#",recordsToReturn);
return recordsToReturn;
}
else{
NSLog(#"Error while creating retrieving mailBodyFor in messaging '%s'", sqlite3_errmsg(database));
sqlite3_close(database);
}
// method to delete data
if (sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK)
{
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
NSString *deleteQuery = [[NSString alloc] initWithFormat:#"delete from users_messages_status where id IN(%#)",ids];
NSLog(#"users_messages_status msg deleteQuery - %#",deleteQuery);
sqlite3_stmt *deleteStmnt;
const char *sql = [deleteQuery cStringUsingEncoding:NSUTF8StringEncoding];
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmnt, NULL) != SQLITE_OK){
NSLog(#"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
}
else{
NSLog(#"successful deletion from users_messages");
}
if(SQLITE_DONE != sqlite3_step(deleteStmnt)){
NSLog(#"Error while deleting. '%s'", sqlite3_errmsg(database));
}
sqlite3_close(database);
Things are going wrong in this sequence
Data is retrieved
'Database is locked' error arises on performing delete operation.
When I retry to perform 1st step.. it now gives same error.
Can anyone suggest me:
If I am doing anything wrong or missing some check?
Is there any way to unlock it when it gives locked error?
Thanks,
Miraaj
It is really uncommon that open/close the database every time you access.
If it is your intended scenario, it would be much better to use a normal file.
Open the database at startup and close at exit. This could solve all your problems.

OSX: How to get a volume name (or bsd name) from a IOUSBDeviceInterface or location id

I'm trying to write an app that associates a particular USB string descriptor (of a USB mass storage device) with its volume or bsd name.
So the code goes through all the connected USB devices, gets the string descriptors and extracts information from one of them. I would like to get the volume name of those USB devices. I can't find the right API to do that.
I have tried to do that:
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
DADiskRef disk_ref = DADiskCreateFromIOMedia(kCFAllocatorDefault,
session,
usb_device_ref);
const char* name = DADiskGetBSDName(disk_ref);
But the DADiskCreateFromIOMedia function returned nil, I assume the usb_device_ref that I passed was not compatible with the io_service_t that the function is expecting.
So how can I get the volume name of a USB device?
Could I use the location id to do that?
Thanks for reading.
-L
FOO_Result result = FOO_SUCCESS;
mach_port_t master_port;
kern_return_t k_result;
io_iterator_t iterator = 0;
io_service_t usb_device_ref;
CFMutableDictionaryRef matching_dictionary = NULL;
// first create a master_port
if (FOO_FAILED(k_result = IOMasterPort(MACH_PORT_NULL, &master_port))) {
fprintf(stderr, "could not create master port, err = %d\n", k_result);
goto cleanup;
}
if ((matching_dictionary = IOServiceMatching(kIOUSBDeviceClassName)) == NULL)
{
fprintf(stderr, "could not create matching dictionary, err = %d\n", k_result);
goto cleanup;
}
if (FOO_FAILED(k_result = IOServiceGetMatchingServices(master_port, matching_dictionary, &iterator))) {
fprintf(stderr, "could not find any matching services, err = %d\n", k_result);
goto cleanup;
}
while (usb_device_ref = IOIteratorNext(iterator))
{
IOReturn err;
IOCFPlugInInterface **iodev; // requires <IOKit/IOCFPlugIn.h>
IOUSBDeviceInterface **dev;
SInt32 score;
err = IOCreatePlugInInterfaceForService(usb_device_ref, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
if (err || !iodev)
{
printf("dealWithDevice: unable to create plugin. ret = %08x, iodev = %p\n", err, iodev);
return;
}
err = (*iodev)->QueryInterface(iodev,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID*)&dev);
(*iodev)->Release(iodev); // done with this
FOO_String string_value;
UInt8 string_index = 0x1;
FOO_Result result = FOO_SUCCESS;
CFStringRef device_name_as_cf_string;
do {
if (FOO_SUCCEEDED(result = FOO_GetStringDescriptor(dev, string_index, 0, string_value))) {
printf("String at index %i is %s\n", string_index, string_value.GetChars());
// extract the command code if it is the FOO string
if (string_value.CompareN("FOO:", 4) == 0) {
FOO_Byte code = 0;
FOO_HexToByte(string_value.GetChars() + 4, code);
// Get other relevant information from the device
io_name_t device_name;
UInt32 location_id = 0;
// Get the USB device's name.
err = IORegistryEntryGetName(usb_device_ref, device_name);
device_name_as_cf_string = CFStringCreateWithCString(kCFAllocatorDefault, device_name,
kCFStringEncodingASCII);
err = (*dev)->GetLocationID(dev, &location_id);
// TODO: get volume or BSD name
// add the device to the list
break;
}
}
string_index++;
} while (FOO_SUCCEEDED(result));
err = (*dev)->USBDeviceClose(dev);
if (err)
{
printf("dealWithDevice: error closing device - %08x\n", err);
(*dev)->Release(dev);
return;
}
err = (*dev)->Release(dev);
if (err)
{
printf("dealWithDevice: error releasing device - %08x\n", err);
return;
}
IOObjectRelease(usb_device_ref); // no longer need this reference
}
Once you have the io_service_t, you can recurse through the IORegistry to find the BSD Name. You do not need to actually create an interface.
#import <IOKit/IOBSD.h>
CFStringRef bsdName = ( CFStringRef ) IORegistryEntrySearchCFProperty ( usbDevice,
kIOServicePlane,
CFSTR ( kIOBSDNameKey ),
kCFAllocatorDefault,
kIORegistryIterateRecursively );
See also:
usbdevs - list mounted USB devices & their volume paths on Mac OS X
https://gist.github.com/atr000/621561

Resources