FileAlias.m
author Jens Alfke <jens@mooseyard.com>
Sat May 31 11:26:17 2008 -0700 (2008-05-31)
changeset 12 66b870428f85
parent 0 d84d25d6cdbb
child 16 ce9c83f7ec14
permissions -rw-r--r--
* Worked around compiler warnings in Test.h when building for iPhone.
* Made Mercurial ignore the documentation files.
     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
   232 
   233 
   234 /*
   235  Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   236  
   237  Redistribution and use in source and binary forms, with or without modification, are permitted
   238  provided that the following conditions are met:
   239  
   240  * Redistributions of source code must retain the above copyright notice, this list of conditions
   241  and the following disclaimer.
   242  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   243  and the following disclaimer in the documentation and/or other materials provided with the
   244  distribution.
   245  
   246  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   247  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   248  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   249  BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   250  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   251   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   252  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   253  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   254  */