FileAlias.m
author Jens Alfke <jens@mooseyard.com>
Sat Mar 08 21:04:41 2008 -0800 (2008-03-08)
changeset 0 d84d25d6cdbb
child 11 e5976864dfe9
permissions -rw-r--r--
Initial checkin.
     1 //
     2 //  FileAlias.m
     3 //  MYUtilities
     4 //
     5 //  Copyright 2008 Jens Alfke. All rights reserved.
     6 //
     7 
     8 #import "FileAlias.h"
     9 #import "FileUtils.h"
    10 
    11 
    12 @implementation FileAlias
    13 
    14 
    15 - (id) initWithFilePath: (NSString*)targetPath 
    16          relativeToPath: (NSString*)fromPath
    17                   error: (NSError**)error
    18 {
    19     NSParameterAssert(targetPath);
    20     self = [super init];
    21     if( self ) {
    22         OSStatus err;
    23         FSRef fromRef, targetRef;
    24         err = PathToFSRef(targetPath, &targetRef);
    25         if( ! err ) {
    26             if( fromPath ) {
    27                 err = PathToFSRef(fromPath,&fromRef);
    28                 if( ! err )
    29                     err = FSNewAlias(&fromRef,&targetRef,&_alias);
    30             } else {
    31                 err = FSNewAlias(NULL,&targetRef,&_alias);
    32             }
    33         }
    34         
    35         if( ! CheckOSErr(err,error) ) {
    36             Warn(@"FileAlias init failed with OSStatus %i",err);
    37             [self release];
    38             return nil;
    39         }
    40     }
    41     return self;
    42 }
    43 
    44 - (id) initWithFilePath: (NSString*)path
    45                   error: (NSError**)error
    46 {
    47     return [self initWithFilePath: path relativeToPath: nil error: error];
    48 }
    49 
    50 
    51 - (void) dealloc
    52 {
    53     if( _alias )
    54         DisposeHandle((Handle)_alias);
    55     [super dealloc];
    56 }
    57 
    58 
    59 - (void)encodeWithCoder:(NSCoder *)coder
    60 {
    61     NSParameterAssert([coder allowsKeyedCoding]);
    62     NSKeyedArchiver *arch = (NSKeyedArchiver*)coder;
    63 
    64     [arch encodeBytes: (const uint8_t *) *_alias 
    65                length: GetHandleSize((Handle)_alias)
    66                forKey: @"aliasHandle"];
    67 }
    68 
    69 
    70 - (id)initWithCoder:(NSCoder *)decoder
    71 {
    72     NSParameterAssert([decoder allowsKeyedCoding]);
    73     NSKeyedUnarchiver *arch = (NSKeyedUnarchiver*)decoder;
    74 
    75     self = [super init];
    76     if( self ) {
    77         Handle handle;
    78         unsigned length;
    79         const void *bytes = [arch decodeBytesForKey:@"aliasHandle" returnedLength: &length];
    80         if( bytes )
    81             PtrToHand(bytes,&handle,length);
    82         if( ! handle ) {
    83             [self release];
    84             return nil;
    85         }
    86         _alias = (AliasHandle) handle;
    87     }
    88     return self;
    89 }
    90 
    91 
    92 - (NSString*) description
    93 {
    94     return [NSString stringWithFormat: @"%@['%@']", [self class],[self originalFilename]];
    95 }
    96 
    97 
    98 - (NSString*) originalPath
    99 {
   100     CFStringRef path = NULL;
   101     OSStatus err = FSCopyAliasInfo(_alias,NULL,NULL,&path,NULL,NULL);
   102     if( err )
   103         return nil;
   104     else
   105         return [(id)path autorelease];
   106 }
   107 
   108 - (NSString*) originalFilename
   109 {
   110     HFSUniStr255 targetName;
   111     OSStatus err = FSCopyAliasInfo(_alias,&targetName,NULL,NULL,NULL,NULL);
   112     if( err )
   113         return nil;
   114     else
   115         return [(id)FSCreateStringFromHFSUniStr(NULL,&targetName) autorelease];
   116 }
   117 
   118 - (NSString*) originalVolumeName
   119 {
   120     HFSUniStr255 volName;
   121     OSStatus err = FSCopyAliasInfo(_alias,NULL,&volName,NULL,NULL,NULL);
   122     if( err )
   123         return nil;
   124     else
   125         return [(id)FSCreateStringFromHFSUniStr(NULL,&volName) autorelease];
   126 }
   127 
   128 - (void) dump
   129 {
   130     HFSUniStr255 targetName,volName;
   131     CFStringRef path;
   132     FSAliasInfoBitmap whichInfo = 0;
   133     FSAliasInfo info;
   134     OSStatus err = FSCopyAliasInfo(_alias,&targetName,&volName,&path,&whichInfo,&info);
   135     if( err ) {
   136         NSLog(@"FSCopyAliasInfo returned error %i",err);
   137         return;
   138     }
   139     NSString *str = (id)FSCreateStringFromHFSUniStr(NULL,&targetName);
   140     NSLog(@"Target name = '%@'",str);
   141     [str release];
   142     str = (id)FSCreateStringFromHFSUniStr(NULL,&volName);
   143     NSLog(@"Volume name = '%@'",str);
   144     [str release];
   145     NSLog(@"Path        = %@",path);
   146     if( path ) CFRelease(path);
   147     NSLog(@"Info bitmap = %08X", whichInfo);
   148 }    
   149 
   150 
   151 #pragma mark -
   152 #pragma mark RESOLVING:
   153 
   154 
   155 - (NSString*) filePathRelativeToPath: (NSString*)fromPath error: (NSError**)error
   156 {
   157     FSRef fromRef, targetRef, *fromRefPtr;
   158     if( fromPath ) {
   159         if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
   160             return NO;
   161         fromRefPtr = &fromRef;
   162     } else {
   163         fromRefPtr = NULL;
   164     }
   165     
   166     Boolean wasChanged;
   167     NSString *targetPath;
   168     if( CheckOSErr( FSResolveAlias(fromRefPtr,_alias,&targetRef,&wasChanged), error)
   169             && CheckOSErr( FSRefToPath(&targetRef,&targetPath), error ) )
   170         return targetPath;
   171     else {
   172         NSLog(@"%@: Couldn't resolve alias!",self);
   173         [self dump];
   174         return nil;
   175     }
   176 }
   177 
   178 - (NSString*) filePath: (NSError**)error
   179 {
   180     return [self filePathRelativeToPath: nil error: error];
   181 }
   182 
   183 
   184 - (NSArray*) findMatchesRelativeToPath: (NSString*)fromPath 
   185                              withRules: (unsigned)rules
   186                                  error: (NSError**)error
   187 {
   188     FSRef fromRef, *fromRefPtr;
   189     if( fromPath ) {
   190         if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
   191             return nil;
   192         fromRefPtr = &fromRef;
   193     } else {
   194         fromRefPtr = NULL;
   195     }
   196     
   197     Boolean wasChanged;
   198     short count = 10;
   199     FSRef matches[count];
   200     
   201 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
   202     if( ! FSMatchAliasBulk(fromRefPtr, rules, _alias, &count, matches, &wasChanged, NULL, NULL), error ) {
   203         NSLog(@"%@: FSMatchAliasBulk failed!",self);
   204         return nil;
   205     }
   206 #else
   207     if( ! CheckOSErr( FSMatchAlias(fromRefPtr,rules,_alias,&count,matches,&wasChanged,NULL,NULL), error) ) {
   208         NSLog(@"%@: FSMatchAlias failed!",self);
   209         return nil;
   210     }
   211 #endif
   212     
   213     NSMutableArray *paths = [NSMutableArray arrayWithCapacity: count];
   214     for( short i=0; i<count; i++ ) {
   215         NSString *path;
   216         if( FSRefToPath(&matches[i],&path) == noErr )
   217             [paths addObject: path];
   218     }
   219     return paths;
   220 }
   221 
   222 
   223 - (NSArray*) findMatches: (NSError**)error
   224 {
   225     return [self findMatchesRelativeToPath: nil
   226                                  withRules: kARMMultVols | kARMSearch | kARMSearchMore | kARMTryFileIDFirst
   227                                      error: error];
   228 }
   229 
   230 
   231 @end