diff -r 46a9fde631f4 -r 75db7bb8dce8 QTfrontend/NSWorkspace_RBAdditions.m --- a/QTfrontend/NSWorkspace_RBAdditions.m Wed Jan 02 11:11:49 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +0,0 @@ -// -// NSWorkspace_RBAdditions.m -// PathProps -// -// Created by Rainer Brockerhoff on 10/04/2007. -// Copyright 2007 Rainer Brockerhoff. All rights reserved. -// - -#import "NSWorkspace_RBAdditions.h" -#include -#include -#include - -NSString* NSWorkspace_RBfstypename = @"NSWorkspace_RBfstypename"; -NSString* NSWorkspace_RBmntonname = @"NSWorkspace_RBmntonname"; -NSString* NSWorkspace_RBmntfromname = @"NSWorkspace_RBmntfromname"; -NSString* NSWorkspace_RBdeviceinfo = @"NSWorkspace_RBdeviceinfo"; -NSString* NSWorkspace_RBimagefilepath = @"NSWorkspace_RBimagefilepath"; -NSString* NSWorkspace_RBconnectiontype = @"NSWorkspace_RBconnectiontype"; -NSString* NSWorkspace_RBpartitionscheme = @"NSWorkspace_RBpartitionscheme"; -NSString* NSWorkspace_RBserverURL = @"NSWorkspace_RBserverURL"; - -// This static funtion concatenates two strings, but first checks several possibilities... -// like one or the other nil, or one containing the other already. - -static NSString* AddPart(NSString* first,NSString* second) { - if (!second) { - return first; - } - second = [second stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - if (first) { - if ([first rangeOfString:second options:NSCaseInsensitiveSearch].location==NSNotFound) { - if ([second rangeOfString:first options:NSCaseInsensitiveSearch].location==NSNotFound) { - return [NSString stringWithFormat:@"%@; %@",first,second]; - } - return second; - } - return first; - } - return second; -} - -// This static functions recurses "upwards" over the IO registry. Returns strings that are concatenated -// and ultimately end up under the NSWorkspace_RBdeviceinfo key. -// This isn't too robust in that it assumes that objects returned by the objectForKey methods are -// either strings or dictionaries. A "standard" implementations would use either only CoreFoundation and -// IOKit calls for this, or do more robust type checking on the returned objects. -// -// Also notice that this works as determined experimentally in 10.4.9, there's no official docs I could find. -// YMMV, and it may stop working in any new version of Mac OS X. - -static NSString* CheckParents(io_object_t thing,NSString* part,NSMutableDictionary* dict) { - NSString* result = part; - io_iterator_t parentsIterator = 0; - kern_return_t kernResult = IORegistryEntryGetParentIterator(thing,kIOServicePlane,&parentsIterator); - if ((kernResult==KERN_SUCCESS)&&parentsIterator) { - io_object_t nextParent = 0; - while ((nextParent = IOIteratorNext(parentsIterator))) { - NSDictionary* props = nil; - NSString* image = nil; - NSString* partition = nil; - NSString* connection = nil; - kernResult = IORegistryEntryCreateCFProperties(nextParent,(CFMutableDictionaryRef*)&props,kCFAllocatorDefault,0); - if (IOObjectConformsTo(nextParent,"IOApplePartitionScheme")) { - partition = [props objectForKey:@"Content Mask"]; - } else if (IOObjectConformsTo(nextParent,"IOMedia")) { - partition = [props objectForKey:@"Content"]; - } else if (IOObjectConformsTo(nextParent,"IODiskImageBlockStorageDeviceOutKernel")) { - NSData* data = nil; - if ((data = [[props objectForKey:@"Protocol Characteristics"] objectForKey:@"Virtual Interface Location Path"])) { - image = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease]; - } - } else if (IOObjectConformsTo(nextParent,"IOHDIXHDDriveInKernel")) { - image = [props objectForKey:@"KDIURLPath"]; - } - NSDictionary* subdict; - if ((subdict = [props objectForKey:@"Protocol Characteristics"])) { - connection = [subdict objectForKey:@"Physical Interconnect"]; - } else { - connection = [props objectForKey:@"Physical Interconnect"]; - } - if (connection) { - [dict setObject:AddPart([dict objectForKey:NSWorkspace_RBconnectiontype],connection) forKey:NSWorkspace_RBconnectiontype]; - } - if (partition) { - [dict setObject:partition forKey:NSWorkspace_RBpartitionscheme]; - } - if (image) { - [dict setObject:image forKey:NSWorkspace_RBimagefilepath]; - } - NSString* value; - if ((subdict = [props objectForKey:@"Device Characteristics"])) { - if ((value = [subdict objectForKey:@"Product Name"])) { - result = AddPart(result,value); - } - if ((value = [subdict objectForKey:@"Product Revision Level"])) { - result = AddPart(result,value); - } - if ((value = [subdict objectForKey:@"Vendor Name"])) { - result = AddPart(result,value); - } - } - if ((value = [props objectForKey:@"USB Serial Number"])) { - result = AddPart(result,value); - } - if ((value = [props objectForKey:@"USB Vendor Name"])) { - result = AddPart(result,value); - } - NSString* cls = [(NSString*)IOObjectCopyClass(nextParent) autorelease]; - if (![cls isEqualToString:@"IOPCIDevice"]) { - -// Uncomment the following line to have the device tree dumped to the console. -// NSLog(@"=================================> %@:%@\n",cls,props); - - result = CheckParents(nextParent,result,dict); - } - IOObjectRelease(nextParent); - } - } - if (parentsIterator) { - IOObjectRelease(parentsIterator); - } - return result; -} - -// This formats the (partially undocumented) AFPXMountInfo info into a string. - -/* -static NSString* FormatAFPURL(AFPXVolMountInfoPtr mountInfo,NSString** devdesc) { - UInt8* work = ((UInt8*)mountInfo)+mountInfo->serverNameOffset; - if (devdesc) { - *devdesc = [[[NSString alloc] initWithBytes:&work[1] length:work[0] encoding:NSUTF8StringEncoding] autorelease]; - } - work = ((UInt8*)mountInfo)+mountInfo->volNameOffset; - NSString* volname = [[[NSString alloc] initWithBytes:&work[1] length:work[0] encoding:NSUTF8StringEncoding] autorelease]; - work = ((UInt8*)mountInfo)+mountInfo->alternateAddressOffset; - AFPAlternateAddress* afpa = (AFPAlternateAddress*)work; - AFPTagData* afpta = (AFPTagData*)(&afpa->fAddressList); - NSString* ip = nil; - NSString* dns = nil; - int i = afpa->fAddressCount; - while ((i-->0)) { - switch (afpta->fType) { - case kAFPTagTypeIP: - if (!ip) { - ip = [[[NSString alloc] initWithBytes:&afpta->fData[0] length:afpta->fLength-2 encoding:NSUTF8StringEncoding] autorelease]; - } - break; - case kAFPTagTypeIPPort: - ip = [NSString stringWithFormat:@"%u.%u.%u.%u:%u",afpta->fData[0],afpta->fData[1],afpta->fData[2],afpta->fData[3],OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[4])]; - break; - case kAFPTagTypeDNS: - dns = [[[NSString alloc] initWithBytes:&afpta->fData[0] length:afpta->fLength-2 encoding:NSUTF8StringEncoding] autorelease]; - break; - case 0x07: - ip = [NSString stringWithFormat:@"[%x:%x:%x:%x:%x:%x:%x:%x]",OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[0]), - OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[2]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[4]), - OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[6]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[8]), - OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[10]),OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[12]), - OSSwapBigToHostInt16(*(UInt16*)&afpta->fData[14])]; - break; - } - afpta = (AFPTagData*)((char*)afpta+afpta->fLength); - } - return [NSString stringWithFormat:@"afp://%@/%@",dns?:(ip?:@""),volname]; -} -*/ - -@implementation NSWorkspace (NSWorkspace_RBAdditions) - -// Returns a NSDictionary with properties for the path. See details in the .h file. -// This assumes that the length of path is less than PATH_MAX (currently 1024 characters). - -- (NSDictionary*)propertiesForPath:(NSString*)path { - const char* ccpath = (const char*)[path fileSystemRepresentation]; - NSMutableDictionary* result = nil; - struct statfs fs; - if (!statfs(ccpath,&fs)) { - NSString* from = [NSString stringWithUTF8String:fs.f_mntfromname]; - result = [NSMutableDictionary dictionaryWithObjectsAndKeys: - [NSString stringWithUTF8String:fs.f_fstypename],NSWorkspace_RBfstypename, - [NSString stringWithUTF8String:fs.f_mntonname],NSWorkspace_RBmntonname, - nil]; - if (strncmp(fs.f_mntfromname,"/dev/",5)==0) { -// For a local volume,get the IO registry tree and search it for further info. - mach_port_t masterPort = 0; - io_iterator_t mediaIterator = 0; - kern_return_t kernResult = IOMasterPort(bootstrap_port,&masterPort); - if (kernResult==KERN_SUCCESS) { - CFMutableDictionaryRef classesToMatch = IOBSDNameMatching(masterPort,0,&fs.f_mntfromname[5]); - if (classesToMatch) { - kernResult = IOServiceGetMatchingServices(masterPort,classesToMatch,&mediaIterator); - if ((kernResult==KERN_SUCCESS)&&mediaIterator) { - io_object_t firstMedia = 0; - while ((firstMedia = IOIteratorNext(mediaIterator))) { - NSString* stuff = CheckParents(firstMedia,nil,result); - if (stuff) { - [result setObject:stuff forKey:NSWorkspace_RBdeviceinfo]; - } - IOObjectRelease(firstMedia); - } - } - } - } - if (mediaIterator) { - IOObjectRelease(mediaIterator); - } - if (masterPort) { - mach_port_deallocate(mach_task_self(),masterPort); - } - } - //Don't need this for disk images, gets around warnings for some deprecated functions - - /* else { -// For a network volume, get the volume reference number and use to get the server URL. - FSRef ref; - if (FSPathMakeRef((const UInt8*)ccpath,&ref,NULL)==noErr) { - FSCatalogInfo info; - if (FSGetCatalogInfo(&ref,kFSCatInfoVolume,&info,NULL,NULL,NULL)==noErr) { - ParamBlockRec pb; - UInt16 vmisize = 0; - VolumeMountInfoHeaderPtr mountInfo = NULL; - pb.ioParam.ioCompletion = NULL; - pb.ioParam.ioNamePtr = NULL; - pb.ioParam.ioVRefNum = info.volume; - pb.ioParam.ioBuffer = (Ptr)&vmisize; - pb.ioParam.ioReqCount = sizeof(vmisize); - if ((PBGetVolMountInfoSize(&pb)==noErr)&&vmisize) { - mountInfo = (VolumeMountInfoHeaderPtr)malloc(vmisize); - if (mountInfo) { - pb.ioParam.ioBuffer = (Ptr)mountInfo; - pb.ioParam.ioReqCount = vmisize; - if (PBGetVolMountInfo(&pb)==noErr) { - NSString* url = nil; - switch (mountInfo->media) { - case AppleShareMediaType: - url = FormatAFPURL((AFPXVolMountInfoPtr)mountInfo,&from); - break; - case 'http': - url = from; - break; - case 'crbm': - case 'nfs_': - case 'cifs': - url = [NSString stringWithUTF8String:(char*)mountInfo+sizeof(VolumeMountInfoHeader)+sizeof(OSType)]; - break; - } - if (url) { - [result setObject:url forKey:NSWorkspace_RBserverURL]; - } - } - } - free(mountInfo); - } - } - } - }*/ - [result setObject:from forKey:NSWorkspace_RBmntfromname]; - } - return result; -} - -@end