jens@0: // jens@0: // FileAlias.m jens@0: // MYUtilities jens@0: // jens@0: // Copyright 2008 Jens Alfke. All rights reserved. jens@0: // jens@0: jens@0: #import "FileAlias.h" jens@0: #import "FileUtils.h" jens@0: jens@0: jens@0: @implementation FileAlias jens@0: jens@0: jens@0: - (id) initWithFilePath: (NSString*)targetPath jens@0: relativeToPath: (NSString*)fromPath jens@0: error: (NSError**)error jens@0: { jens@0: NSParameterAssert(targetPath); jens@0: self = [super init]; jens@0: if( self ) { jens@0: OSStatus err; jens@0: FSRef fromRef, targetRef; jens@0: err = PathToFSRef(targetPath, &targetRef); jens@0: if( ! err ) { jens@0: if( fromPath ) { jens@0: err = PathToFSRef(fromPath,&fromRef); jens@0: if( ! err ) jens@0: err = FSNewAlias(&fromRef,&targetRef,&_alias); jens@0: } else { jens@0: err = FSNewAlias(NULL,&targetRef,&_alias); jens@0: } jens@0: } jens@0: jens@0: if( ! CheckOSErr(err,error) ) { jens@0: Warn(@"FileAlias init failed with OSStatus %i",err); jens@0: [self release]; jens@0: return nil; jens@0: } jens@0: } jens@0: return self; jens@0: } jens@0: jens@0: - (id) initWithFilePath: (NSString*)path jens@0: error: (NSError**)error jens@0: { jens@0: return [self initWithFilePath: path relativeToPath: nil error: error]; jens@0: } jens@0: jens@0: jens@0: - (void) dealloc jens@0: { jens@0: if( _alias ) jens@0: DisposeHandle((Handle)_alias); jens@0: [super dealloc]; jens@0: } jens@0: jens@0: jens@0: - (void)encodeWithCoder:(NSCoder *)coder jens@0: { jens@0: NSParameterAssert([coder allowsKeyedCoding]); jens@0: NSKeyedArchiver *arch = (NSKeyedArchiver*)coder; jens@0: jens@0: [arch encodeBytes: (const uint8_t *) *_alias jens@0: length: GetHandleSize((Handle)_alias) jens@0: forKey: @"aliasHandle"]; jens@0: } jens@0: jens@0: jens@0: - (id)initWithCoder:(NSCoder *)decoder jens@0: { jens@0: NSParameterAssert([decoder allowsKeyedCoding]); jens@0: NSKeyedUnarchiver *arch = (NSKeyedUnarchiver*)decoder; jens@0: jens@0: self = [super init]; jens@0: if( self ) { jens@0: Handle handle; jens@0: unsigned length; jens@0: const void *bytes = [arch decodeBytesForKey:@"aliasHandle" returnedLength: &length]; jens@0: if( bytes ) jens@0: PtrToHand(bytes,&handle,length); jens@0: if( ! handle ) { jens@0: [self release]; jens@0: return nil; jens@0: } jens@0: _alias = (AliasHandle) handle; jens@0: } jens@0: return self; jens@0: } jens@0: jens@0: jens@0: - (NSString*) description jens@0: { jens@0: return [NSString stringWithFormat: @"%@['%@']", [self class],[self originalFilename]]; jens@0: } jens@0: jens@0: jens@0: - (NSString*) originalPath jens@0: { jens@0: CFStringRef path = NULL; jens@0: OSStatus err = FSCopyAliasInfo(_alias,NULL,NULL,&path,NULL,NULL); jens@0: if( err ) jens@0: return nil; jens@0: else jens@0: return [(id)path autorelease]; jens@0: } jens@0: jens@0: - (NSString*) originalFilename jens@0: { jens@0: HFSUniStr255 targetName; jens@0: OSStatus err = FSCopyAliasInfo(_alias,&targetName,NULL,NULL,NULL,NULL); jens@0: if( err ) jens@0: return nil; jens@0: else jens@0: return [(id)FSCreateStringFromHFSUniStr(NULL,&targetName) autorelease]; jens@0: } jens@0: jens@0: - (NSString*) originalVolumeName jens@0: { jens@0: HFSUniStr255 volName; jens@0: OSStatus err = FSCopyAliasInfo(_alias,NULL,&volName,NULL,NULL,NULL); jens@0: if( err ) jens@0: return nil; jens@0: else jens@0: return [(id)FSCreateStringFromHFSUniStr(NULL,&volName) autorelease]; jens@0: } jens@0: jens@0: - (void) dump jens@0: { jens@0: HFSUniStr255 targetName,volName; jens@0: CFStringRef path; jens@0: FSAliasInfoBitmap whichInfo = 0; jens@0: FSAliasInfo info; jens@0: OSStatus err = FSCopyAliasInfo(_alias,&targetName,&volName,&path,&whichInfo,&info); jens@0: if( err ) { jens@0: NSLog(@"FSCopyAliasInfo returned error %i",err); jens@0: return; jens@0: } jens@0: NSString *str = (id)FSCreateStringFromHFSUniStr(NULL,&targetName); jens@0: NSLog(@"Target name = '%@'",str); jens@0: [str release]; jens@0: str = (id)FSCreateStringFromHFSUniStr(NULL,&volName); jens@0: NSLog(@"Volume name = '%@'",str); jens@0: [str release]; jens@0: NSLog(@"Path = %@",path); jens@0: if( path ) CFRelease(path); jens@0: NSLog(@"Info bitmap = %08X", whichInfo); jens@0: } jens@0: jens@0: jens@0: #pragma mark - jens@0: #pragma mark RESOLVING: jens@0: jens@0: jens@0: - (NSString*) filePathRelativeToPath: (NSString*)fromPath error: (NSError**)error jens@0: { jens@0: FSRef fromRef, targetRef, *fromRefPtr; jens@0: if( fromPath ) { jens@0: if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) ) jens@0: return NO; jens@0: fromRefPtr = &fromRef; jens@0: } else { jens@0: fromRefPtr = NULL; jens@0: } jens@0: jens@0: Boolean wasChanged; jens@0: NSString *targetPath; jens@0: if( CheckOSErr( FSResolveAlias(fromRefPtr,_alias,&targetRef,&wasChanged), error) jens@0: && CheckOSErr( FSRefToPath(&targetRef,&targetPath), error ) ) jens@0: return targetPath; jens@0: else { jens@0: NSLog(@"%@: Couldn't resolve alias!",self); jens@0: [self dump]; jens@0: return nil; jens@0: } jens@0: } jens@0: jens@0: - (NSString*) filePath: (NSError**)error jens@0: { jens@0: return [self filePathRelativeToPath: nil error: error]; jens@0: } jens@0: jens@0: jens@0: - (NSArray*) findMatchesRelativeToPath: (NSString*)fromPath jens@0: withRules: (unsigned)rules jens@0: error: (NSError**)error jens@0: { jens@0: FSRef fromRef, *fromRefPtr; jens@0: if( fromPath ) { jens@0: if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) ) jens@0: return nil; jens@0: fromRefPtr = &fromRef; jens@0: } else { jens@0: fromRefPtr = NULL; jens@0: } jens@0: jens@0: Boolean wasChanged; jens@0: short count = 10; jens@0: FSRef matches[count]; jens@0: jens@0: #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 jens@0: if( ! FSMatchAliasBulk(fromRefPtr, rules, _alias, &count, matches, &wasChanged, NULL, NULL), error ) { jens@0: NSLog(@"%@: FSMatchAliasBulk failed!",self); jens@0: return nil; jens@0: } jens@0: #else jens@0: if( ! CheckOSErr( FSMatchAlias(fromRefPtr,rules,_alias,&count,matches,&wasChanged,NULL,NULL), error) ) { jens@0: NSLog(@"%@: FSMatchAlias failed!",self); jens@0: return nil; jens@0: } jens@0: #endif jens@0: jens@0: NSMutableArray *paths = [NSMutableArray arrayWithCapacity: count]; jens@0: for( short i=0; i