FileAlias.m
author Jens Alfke <jens@mooseyard.com>
Sun Jun 01 14:01:44 2008 -0700 (2008-06-01)
changeset 13 c59dec088990
parent 0 d84d25d6cdbb
child 16 ce9c83f7ec14
permissions -rw-r--r--
* Made Test.h work with regular C99 without GCC extensions.
* Copied the necessary Google Toolbox source files into the project, so users don't have to download an additional library.
jens@0
     1
//
jens@0
     2
//  FileAlias.m
jens@0
     3
//  MYUtilities
jens@0
     4
//
jens@0
     5
//  Copyright 2008 Jens Alfke. All rights reserved.
jens@0
     6
//
jens@0
     7
jens@0
     8
#import "FileAlias.h"
jens@0
     9
#import "FileUtils.h"
jens@0
    10
jens@0
    11
jens@0
    12
@implementation FileAlias
jens@0
    13
jens@0
    14
jens@0
    15
- (id) initWithFilePath: (NSString*)targetPath 
jens@0
    16
         relativeToPath: (NSString*)fromPath
jens@0
    17
                  error: (NSError**)error
jens@0
    18
{
jens@0
    19
    NSParameterAssert(targetPath);
jens@0
    20
    self = [super init];
jens@0
    21
    if( self ) {
jens@0
    22
        OSStatus err;
jens@0
    23
        FSRef fromRef, targetRef;
jens@0
    24
        err = PathToFSRef(targetPath, &targetRef);
jens@0
    25
        if( ! err ) {
jens@0
    26
            if( fromPath ) {
jens@0
    27
                err = PathToFSRef(fromPath,&fromRef);
jens@0
    28
                if( ! err )
jens@0
    29
                    err = FSNewAlias(&fromRef,&targetRef,&_alias);
jens@0
    30
            } else {
jens@0
    31
                err = FSNewAlias(NULL,&targetRef,&_alias);
jens@0
    32
            }
jens@0
    33
        }
jens@0
    34
        
jens@0
    35
        if( ! CheckOSErr(err,error) ) {
jens@0
    36
            Warn(@"FileAlias init failed with OSStatus %i",err);
jens@0
    37
            [self release];
jens@0
    38
            return nil;
jens@0
    39
        }
jens@0
    40
    }
jens@0
    41
    return self;
jens@0
    42
}
jens@0
    43
jens@0
    44
- (id) initWithFilePath: (NSString*)path
jens@0
    45
                  error: (NSError**)error
jens@0
    46
{
jens@0
    47
    return [self initWithFilePath: path relativeToPath: nil error: error];
jens@0
    48
}
jens@0
    49
jens@0
    50
jens@0
    51
- (void) dealloc
jens@0
    52
{
jens@0
    53
    if( _alias )
jens@0
    54
        DisposeHandle((Handle)_alias);
jens@0
    55
    [super dealloc];
jens@0
    56
}
jens@0
    57
jens@0
    58
jens@0
    59
- (void)encodeWithCoder:(NSCoder *)coder
jens@0
    60
{
jens@0
    61
    NSParameterAssert([coder allowsKeyedCoding]);
jens@0
    62
    NSKeyedArchiver *arch = (NSKeyedArchiver*)coder;
jens@0
    63
jens@0
    64
    [arch encodeBytes: (const uint8_t *) *_alias 
jens@0
    65
               length: GetHandleSize((Handle)_alias)
jens@0
    66
               forKey: @"aliasHandle"];
jens@0
    67
}
jens@0
    68
jens@0
    69
jens@0
    70
- (id)initWithCoder:(NSCoder *)decoder
jens@0
    71
{
jens@0
    72
    NSParameterAssert([decoder allowsKeyedCoding]);
jens@0
    73
    NSKeyedUnarchiver *arch = (NSKeyedUnarchiver*)decoder;
jens@0
    74
jens@0
    75
    self = [super init];
jens@0
    76
    if( self ) {
jens@0
    77
        Handle handle;
jens@0
    78
        unsigned length;
jens@0
    79
        const void *bytes = [arch decodeBytesForKey:@"aliasHandle" returnedLength: &length];
jens@0
    80
        if( bytes )
jens@0
    81
            PtrToHand(bytes,&handle,length);
jens@0
    82
        if( ! handle ) {
jens@0
    83
            [self release];
jens@0
    84
            return nil;
jens@0
    85
        }
jens@0
    86
        _alias = (AliasHandle) handle;
jens@0
    87
    }
jens@0
    88
    return self;
jens@0
    89
}
jens@0
    90
jens@0
    91
jens@0
    92
- (NSString*) description
jens@0
    93
{
jens@0
    94
    return [NSString stringWithFormat: @"%@['%@']", [self class],[self originalFilename]];
jens@0
    95
}
jens@0
    96
jens@0
    97
jens@0
    98
- (NSString*) originalPath
jens@0
    99
{
jens@0
   100
    CFStringRef path = NULL;
jens@0
   101
    OSStatus err = FSCopyAliasInfo(_alias,NULL,NULL,&path,NULL,NULL);
jens@0
   102
    if( err )
jens@0
   103
        return nil;
jens@0
   104
    else
jens@0
   105
        return [(id)path autorelease];
jens@0
   106
}
jens@0
   107
jens@0
   108
- (NSString*) originalFilename
jens@0
   109
{
jens@0
   110
    HFSUniStr255 targetName;
jens@0
   111
    OSStatus err = FSCopyAliasInfo(_alias,&targetName,NULL,NULL,NULL,NULL);
jens@0
   112
    if( err )
jens@0
   113
        return nil;
jens@0
   114
    else
jens@0
   115
        return [(id)FSCreateStringFromHFSUniStr(NULL,&targetName) autorelease];
jens@0
   116
}
jens@0
   117
jens@0
   118
- (NSString*) originalVolumeName
jens@0
   119
{
jens@0
   120
    HFSUniStr255 volName;
jens@0
   121
    OSStatus err = FSCopyAliasInfo(_alias,NULL,&volName,NULL,NULL,NULL);
jens@0
   122
    if( err )
jens@0
   123
        return nil;
jens@0
   124
    else
jens@0
   125
        return [(id)FSCreateStringFromHFSUniStr(NULL,&volName) autorelease];
jens@0
   126
}
jens@0
   127
jens@0
   128
- (void) dump
jens@0
   129
{
jens@0
   130
    HFSUniStr255 targetName,volName;
jens@0
   131
    CFStringRef path;
jens@0
   132
    FSAliasInfoBitmap whichInfo = 0;
jens@0
   133
    FSAliasInfo info;
jens@0
   134
    OSStatus err = FSCopyAliasInfo(_alias,&targetName,&volName,&path,&whichInfo,&info);
jens@0
   135
    if( err ) {
jens@0
   136
        NSLog(@"FSCopyAliasInfo returned error %i",err);
jens@0
   137
        return;
jens@0
   138
    }
jens@0
   139
    NSString *str = (id)FSCreateStringFromHFSUniStr(NULL,&targetName);
jens@0
   140
    NSLog(@"Target name = '%@'",str);
jens@0
   141
    [str release];
jens@0
   142
    str = (id)FSCreateStringFromHFSUniStr(NULL,&volName);
jens@0
   143
    NSLog(@"Volume name = '%@'",str);
jens@0
   144
    [str release];
jens@0
   145
    NSLog(@"Path        = %@",path);
jens@0
   146
    if( path ) CFRelease(path);
jens@0
   147
    NSLog(@"Info bitmap = %08X", whichInfo);
jens@0
   148
}    
jens@0
   149
jens@0
   150
jens@0
   151
#pragma mark -
jens@0
   152
#pragma mark RESOLVING:
jens@0
   153
jens@0
   154
jens@0
   155
- (NSString*) filePathRelativeToPath: (NSString*)fromPath error: (NSError**)error
jens@0
   156
{
jens@0
   157
    FSRef fromRef, targetRef, *fromRefPtr;
jens@0
   158
    if( fromPath ) {
jens@0
   159
        if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
jens@0
   160
            return NO;
jens@0
   161
        fromRefPtr = &fromRef;
jens@0
   162
    } else {
jens@0
   163
        fromRefPtr = NULL;
jens@0
   164
    }
jens@0
   165
    
jens@0
   166
    Boolean wasChanged;
jens@0
   167
    NSString *targetPath;
jens@0
   168
    if( CheckOSErr( FSResolveAlias(fromRefPtr,_alias,&targetRef,&wasChanged), error)
jens@0
   169
            && CheckOSErr( FSRefToPath(&targetRef,&targetPath), error ) )
jens@0
   170
        return targetPath;
jens@0
   171
    else {
jens@0
   172
        NSLog(@"%@: Couldn't resolve alias!",self);
jens@0
   173
        [self dump];
jens@0
   174
        return nil;
jens@0
   175
    }
jens@0
   176
}
jens@0
   177
jens@0
   178
- (NSString*) filePath: (NSError**)error
jens@0
   179
{
jens@0
   180
    return [self filePathRelativeToPath: nil error: error];
jens@0
   181
}
jens@0
   182
jens@0
   183
jens@0
   184
- (NSArray*) findMatchesRelativeToPath: (NSString*)fromPath 
jens@0
   185
                             withRules: (unsigned)rules
jens@0
   186
                                 error: (NSError**)error
jens@0
   187
{
jens@0
   188
    FSRef fromRef, *fromRefPtr;
jens@0
   189
    if( fromPath ) {
jens@0
   190
        if( ! CheckOSErr( PathToFSRef(fromPath,&fromRef), error ) )
jens@0
   191
            return nil;
jens@0
   192
        fromRefPtr = &fromRef;
jens@0
   193
    } else {
jens@0
   194
        fromRefPtr = NULL;
jens@0
   195
    }
jens@0
   196
    
jens@0
   197
    Boolean wasChanged;
jens@0
   198
    short count = 10;
jens@0
   199
    FSRef matches[count];
jens@0
   200
    
jens@0
   201
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
jens@0
   202
    if( ! FSMatchAliasBulk(fromRefPtr, rules, _alias, &count, matches, &wasChanged, NULL, NULL), error ) {
jens@0
   203
        NSLog(@"%@: FSMatchAliasBulk failed!",self);
jens@0
   204
        return nil;
jens@0
   205
    }
jens@0
   206
#else
jens@0
   207
    if( ! CheckOSErr( FSMatchAlias(fromRefPtr,rules,_alias,&count,matches,&wasChanged,NULL,NULL), error) ) {
jens@0
   208
        NSLog(@"%@: FSMatchAlias failed!",self);
jens@0
   209
        return nil;
jens@0
   210
    }
jens@0
   211
#endif
jens@0
   212
    
jens@0
   213
    NSMutableArray *paths = [NSMutableArray arrayWithCapacity: count];
jens@0
   214
    for( short i=0; i<count; i++ ) {
jens@0
   215
        NSString *path;
jens@0
   216
        if( FSRefToPath(&matches[i],&path) == noErr )
jens@0
   217
            [paths addObject: path];
jens@0
   218
    }
jens@0
   219
    return paths;
jens@0
   220
}
jens@0
   221
jens@0
   222
jens@0
   223
- (NSArray*) findMatches: (NSError**)error
jens@0
   224
{
jens@0
   225
    return [self findMatchesRelativeToPath: nil
jens@0
   226
                                 withRules: kARMMultVols | kARMSearch | kARMSearchMore | kARMTryFileIDFirst
jens@0
   227
                                     error: error];
jens@0
   228
}
jens@0
   229
jens@0
   230
jens@0
   231
@end
jens@11
   232
jens@11
   233
jens@11
   234
/*
jens@11
   235
 Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
jens@11
   236
 
jens@11
   237
 Redistribution and use in source and binary forms, with or without modification, are permitted
jens@11
   238
 provided that the following conditions are met:
jens@11
   239
 
jens@11
   240
 * Redistributions of source code must retain the above copyright notice, this list of conditions
jens@11
   241
 and the following disclaimer.
jens@11
   242
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
jens@11
   243
 and the following disclaimer in the documentation and/or other materials provided with the
jens@11
   244
 distribution.
jens@11
   245
 
jens@11
   246
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
jens@11
   247
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
jens@11
   248
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
jens@11
   249
 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
jens@11
   250
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
jens@11
   251
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
jens@11
   252
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
jens@11
   253
 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jens@11
   254
 */