1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/FileAlias.m Wed Apr 02 14:45:33 2008 -0700
1.3 @@ -0,0 +1,231 @@
1.4 +//
1.5 +// FileAlias.m
1.6 +// MYUtilities
1.7 +//
1.8 +// Copyright 2008 Jens Alfke. All rights reserved.
1.9 +//
1.10 +
1.11 +#import "FileAlias.h"
1.12 +#import "FileUtils.h"
1.13 +
1.14 +
1.15 +@implementation FileAlias
1.16 +
1.17 +
1.18 +- (id) initWithFilePath: (NSString*)targetPath
1.19 + relativeToPath: (NSString*)fromPath
1.20 + error: (NSError**)error
1.21 +{
1.22 + NSParameterAssert(targetPath);
1.23 + self = [super init];
1.24 + if( self ) {
1.25 + OSStatus err;
1.26 + FSRef fromRef, targetRef;
1.27 + err = PathToFSRef(targetPath, &targetRef);
1.28 + if( ! err ) {
1.29 + if( fromPath ) {
1.30 + err = PathToFSRef(fromPath,&fromRef);
1.31 + if( ! err )
1.32 + err = FSNewAlias(&fromRef,&targetRef,&_alias);
1.33 + } else {
1.34 + err = FSNewAlias(NULL,&targetRef,&_alias);
1.35 + }
1.36 + }
1.37 +
1.38 + if( ! CheckOSErr(err,error) ) {
1.39 + Warn(@"FileAlias init failed with OSStatus %i",err);
1.40 + [self release];
1.41 + return nil;
1.42 + }
1.43 + }
1.44 + return self;
1.45 +}
1.46 +
1.47 +- (id) initWithFilePath: (NSString*)path
1.48 + error: (NSError**)error
1.49 +{
1.50 + return [self initWithFilePath: path relativeToPath: nil error: error];
1.51 +}
1.52 +
1.53 +
1.54 +- (void) dealloc
1.55 +{
1.56 + if( _alias )
1.57 + DisposeHandle((Handle)_alias);
1.58 + [super dealloc];
1.59 +}
1.60 +
1.61 +
1.62 +- (void)encodeWithCoder:(NSCoder *)coder
1.63 +{
1.64 + NSParameterAssert([coder allowsKeyedCoding]);
1.65 + NSKeyedArchiver *arch = (NSKeyedArchiver*)coder;
1.66 +
1.67 + [arch encodeBytes: (const uint8_t *) *_alias
1.68 + length: GetHandleSize((Handle)_alias)
1.69 + forKey: @"aliasHandle"];
1.70 +}
1.71 +
1.72 +
1.73 +- (id)initWithCoder:(NSCoder *)decoder
1.74 +{
1.75 + NSParameterAssert([decoder allowsKeyedCoding]);
1.76 + NSKeyedUnarchiver *arch = (NSKeyedUnarchiver*)decoder;
1.77 +
1.78 + self = [super init];
1.79 + if( self ) {
1.80 + Handle handle;
1.81 + unsigned length;
1.82 + const void *bytes = [arch decodeBytesForKey:@"aliasHandle" returnedLength: &length];
1.83 + if( bytes )
1.84 + PtrToHand(bytes,&handle,length);
1.85 + if( ! handle ) {
1.86 + [self release];
1.87 + return nil;
1.88 + }
1.89 + _alias = (AliasHandle) handle;
1.90 + }
1.91 + return self;
1.92 +}
1.93 +
1.94 +
1.95 +- (NSString*) description
1.96 +{
1.97 + return [NSString stringWithFormat: @"%@['%@']", [self class],[self originalFilename]];
1.98 +}
1.99 +
1.100 +
1.101 +- (NSString*) originalPath
1.102 +{
1.103 + CFStringRef path = NULL;
1.104 + OSStatus err = FSCopyAliasInfo(_alias,NULL,NULL,&path,NULL,NULL);
1.105 + if( err )
1.106 + return nil;
1.107 + else
1.108 + return [(id)path autorelease];
1.109 +}
1.110 +
1.111 +- (NSString*) originalFilename
1.112 +{
1.113 + HFSUniStr255 targetName;
1.114 + OSStatus err = FSCopyAliasInfo(_alias,&targetName,NULL,NULL,NULL,NULL);
1.115 + if( err )
1.116 + return nil;
1.117 + else
1.118 + return [(id)FSCreateStringFromHFSUniStr(NULL,&targetName) autorelease];
1.119 +}
1.120 +
1.121 +- (NSString*) originalVolumeName
1.122 +{
1.123 + HFSUniStr255 volName;
1.124 + OSStatus err = FSCopyAliasInfo(_alias,NULL,&volName,NULL,NULL,NULL);
1.125 + if( err )
1.126 + return nil;
1.127 + else
1.128 + return [(id)FSCreateStringFromHFSUniStr(NULL,&volName) autorelease];
1.129 +}
1.130 +
1.131 +- (void) dump
1.132 +{
1.133 + HFSUniStr255 targetName,volName;
1.134 + CFStringRef path;
1.135 + FSAliasInfoBitmap whichInfo = 0;
1.136 + FSAliasInfo info;
1.137 + OSStatus err = FSCopyAliasInfo(_alias,&targetName,&volName,&path,&whichInfo,&info);
1.138 + if( err ) {
1.139 + NSLog(@"FSCopyAliasInfo returned error %i",err);
1.140 + return;
1.141 + }
1.142 + NSString *str = (id)FSCreateStringFromHFSUniStr(NULL,&targetName);
1.143 + NSLog(@"Target name = '%@'",str);
1.144 + [str release];
1.145 + str = (id)FSCreateStringFromHFSUniStr(NULL,&volName);
1.146 + NSLog(@"Volume name = '%@'",str);
1.147 + [str release];
1.148 + NSLog(@"Path = %@",path);
1.149 + if( path ) CFRelease(path);
1.150 + NSLog(@"Info bitmap = %08X", whichInfo);
1.151 +}
1.152 +
1.153 +
1.154 +#pragma mark -
1.155 +#pragma mark RESOLVING:
1.156 +
1.157 +
1.158 +- (NSString*) filePathRelativeToPath: (NSString*)fromPath error: (NSError**)error
1.159 +{
1.160 + FSRef fromRef, targetRef, *fromRefPtr;
1.161 + if( fromPath ) {
1.162 + if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
1.163 + return NO;
1.164 + fromRefPtr = &fromRef;
1.165 + } else {
1.166 + fromRefPtr = NULL;
1.167 + }
1.168 +
1.169 + Boolean wasChanged;
1.170 + NSString *targetPath;
1.171 + if( CheckOSErr( FSResolveAlias(fromRefPtr,_alias,&targetRef,&wasChanged), error)
1.172 + && CheckOSErr( FSRefToPath(&targetRef,&targetPath), error ) )
1.173 + return targetPath;
1.174 + else {
1.175 + NSLog(@"%@: Couldn't resolve alias!",self);
1.176 + [self dump];
1.177 + return nil;
1.178 + }
1.179 +}
1.180 +
1.181 +- (NSString*) filePath: (NSError**)error
1.182 +{
1.183 + return [self filePathRelativeToPath: nil error: error];
1.184 +}
1.185 +
1.186 +
1.187 +- (NSArray*) findMatchesRelativeToPath: (NSString*)fromPath
1.188 + withRules: (unsigned)rules
1.189 + error: (NSError**)error
1.190 +{
1.191 + FSRef fromRef, *fromRefPtr;
1.192 + if( fromPath ) {
1.193 + if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
1.194 + return nil;
1.195 + fromRefPtr = &fromRef;
1.196 + } else {
1.197 + fromRefPtr = NULL;
1.198 + }
1.199 +
1.200 + Boolean wasChanged;
1.201 + short count = 10;
1.202 + FSRef matches[count];
1.203 +
1.204 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
1.205 + if( ! FSMatchAliasBulk(fromRefPtr, rules, _alias, &count, matches, &wasChanged, NULL, NULL), error ) {
1.206 + NSLog(@"%@: FSMatchAliasBulk failed!",self);
1.207 + return nil;
1.208 + }
1.209 +#else
1.210 + if( ! CheckOSErr( FSMatchAlias(fromRefPtr,rules,_alias,&count,matches,&wasChanged,NULL,NULL), error) ) {
1.211 + NSLog(@"%@: FSMatchAlias failed!",self);
1.212 + return nil;
1.213 + }
1.214 +#endif
1.215 +
1.216 + NSMutableArray *paths = [NSMutableArray arrayWithCapacity: count];
1.217 + for( short i=0; i<count; i++ ) {
1.218 + NSString *path;
1.219 + if( FSRefToPath(&matches[i],&path) == noErr )
1.220 + [paths addObject: path];
1.221 + }
1.222 + return paths;
1.223 +}
1.224 +
1.225 +
1.226 +- (NSArray*) findMatches: (NSError**)error
1.227 +{
1.228 + return [self findMatchesRelativeToPath: nil
1.229 + withRules: kARMMultVols | kARMSearch | kARMSearchMore | kARMTryFileIDFirst
1.230 + error: error];
1.231 +}
1.232 +
1.233 +
1.234 +@end