Ticket #167: BDAlias.m

File BDAlias.m, 7.5 KB (added by cluthi81, 15 years ago)

Cocoa wrapper around alias records

Line 
1/*
2    Copyright (c) 2001-2002, bDistributed.com, Inc.
3    All rights reserved.
4
5    Redistribution and use in source and binary forms, with or
6    without modification, are permitted provided that the following
7    conditions are met:
8
9    *   Redistributions of source code must retain the above
10        copyright notice, this list of conditions and the following
11        disclaimer.
12   
13    *   Redistributions in binary form must reproduce the above
14        copyright notice, this list of conditions and the following
15        disclaimer in the documentation and/or other materials
16        provided with the distribution.
17   
18    *   Neither the name of bDistributed.com, Inc. nor the names of
19        its contributors may be used to endorse or promote products
20        derived from this software without specific prior written
21        permission.
22
23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24    CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27    DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
28    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
31    OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35    OF SUCH DAMAGE.
36*/
37
38#include <assert.h>
39
40#import "BDAlias.h"
41
42
43static Handle DataToHandle(CFDataRef inData);
44static CFDataRef HandleToData(Handle inHandle);
45
46static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef);
47static CFStringRef FSRefToPathCopy(const FSRef *inRef);
48
49
50static Handle DataToHandle(CFDataRef inData)
51{
52    CFIndex     len;
53    Handle      handle = NULL;
54   
55    if (inData == NULL) {
56        return NULL;
57    }
58   
59    len = CFDataGetLength(inData);
60   
61    handle = NewHandle(len);
62   
63    if ((handle != NULL) && (len > 0)) {
64        HLock(handle);
65        BlockMoveData(CFDataGetBytePtr(inData), *handle, len);
66        HUnlock(handle);
67    }
68   
69    return handle;
70}
71
72static CFDataRef HandleToData(Handle inHandle)
73{
74    CFDataRef   data = NULL;
75    CFIndex     len;
76    SInt8       handleState;
77   
78    if (inHandle == NULL) {
79        return NULL;
80    }
81   
82    len = GetHandleSize(inHandle);
83   
84    handleState = HGetState(inHandle);
85   
86    HLock(inHandle);
87   
88    data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) *inHandle, len);
89   
90    HSetState(inHandle, handleState);
91   
92    return data;
93}
94
95static OSStatus PathToFSRef(CFStringRef inPath, FSRef *outRef)
96{
97    CFURLRef    tempURL = NULL;
98    Boolean     gotRef = false;
99   
100    tempURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, inPath,
101                                            kCFURLPOSIXPathStyle, false);
102   
103    if (tempURL == NULL) {
104        return fnfErr;
105    }
106   
107    gotRef = CFURLGetFSRef(tempURL, outRef);
108   
109    CFRelease(tempURL);
110   
111    if (gotRef == false) {
112        return fnfErr;
113    }
114   
115    return noErr;
116}
117
118static CFStringRef FSRefToPathCopy(const FSRef *inRef)
119{
120    CFURLRef    tempURL = NULL;
121    CFStringRef result = NULL;
122   
123    if (inRef != NULL) {
124        tempURL = CFURLCreateFromFSRef(kCFAllocatorDefault, inRef);
125       
126        if (tempURL == NULL) {
127            return NULL;
128        }
129       
130        result = CFURLCopyFileSystemPath(tempURL, kCFURLPOSIXPathStyle);
131       
132        CFRelease(tempURL);
133    }
134   
135    return result;
136}
137
138
139@implementation BDAlias
140
141- (id)initWithAliasHandle:(AliasHandle)alias
142{
143    id ret = [super init];
144   
145    if (ret != nil) {
146        _alias = alias;
147    }
148   
149    return ret;
150}
151
152- (id)initWithData:(NSData *)data
153{
154    return [self initWithAliasHandle:(AliasHandle)DataToHandle((CFDataRef) data)];
155}
156
157- (id)initWithPath:(NSString *)fullPath
158{
159    OSStatus    anErr = noErr;
160    FSRef               ref;
161   
162    anErr = PathToFSRef((CFStringRef) fullPath, &ref);
163   
164    if (anErr != noErr) {
165        return nil;
166    }
167   
168    return [self initWithFSRef:&ref];;
169}
170
171- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath
172{
173    OSStatus    anErr = noErr;
174    FSRef               ref, relRef;
175   
176    anErr = PathToFSRef((CFStringRef) [relPath stringByAppendingPathComponent:path],
177                        &ref);
178   
179    if (anErr != noErr) {
180        return nil;
181    }
182   
183    anErr = PathToFSRef((CFStringRef) relPath, &relRef);
184   
185    if (anErr != noErr) {
186        return nil;
187    }
188   
189    return [self initWithFSRef:&ref relativeToFSRef:&relRef];
190}
191
192- (id)initWithFSRef:(FSRef *)ref
193{
194    return [self initWithFSRef:ref relativeToFSRef:NULL];
195}
196
197- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
198{
199    OSStatus    anErr = noErr;
200    AliasHandle alias = NULL;
201   
202    anErr = FSNewAlias(relRef, ref, &alias);
203   
204    if (anErr != noErr) {
205        return nil;
206    }
207   
208    return [self initWithAliasHandle:alias];
209}
210
211- (void)dealloc
212{
213    if (_alias != NULL) {
214        DisposeHandle((Handle) _alias);
215        _alias = NULL;
216    }
217   
218    [super dealloc];
219}
220
221- (AliasHandle)alias
222{
223    return _alias;
224}
225
226- (void)setAlias:(AliasHandle)newAlias
227{
228    if (_alias != NULL) {
229        DisposeHandle((Handle) _alias);
230    }
231   
232    _alias = newAlias;
233}
234
235- (NSData *)aliasData
236{
237    NSData *result;
238   
239    result = (NSData *)HandleToData((Handle) _alias);
240   
241    return [result autorelease];
242}
243
244- (void)setAliasData:(NSData *)newAliasData
245{
246    [self setAlias:(AliasHandle) DataToHandle((CFDataRef) newAliasData)];
247}
248
249- (NSString *)fullPath
250{
251    return [self fullPathRelativeToPath:nil];
252}
253
254- (NSString *)fullPathWithDefault:(NSString *)defaultPath
255{
256    NSString *fullPath = [self fullPath];
257    return fullPath ? fullPath : [defaultPath stringByExpandingTildeInPath];
258}
259
260- (NSString *)fullPathRelativeToPath:(NSString *)relPath
261{
262    OSStatus    anErr = noErr;
263    FSRef       relPathRef;
264    FSRef       tempRef;
265    NSString    *result = nil;
266    Boolean     wasChanged;
267   
268    if (_alias != NULL) {
269        if (relPath != nil) {
270            anErr = PathToFSRef((CFStringRef)relPath, &relPathRef);
271           
272            if (anErr != noErr) {
273                return NULL;
274            }
275           
276            anErr = FSResolveAlias(&relPathRef, _alias, &tempRef, &wasChanged);
277        } else {
278            anErr = FSResolveAlias(NULL, _alias, &tempRef, &wasChanged);
279        }
280       
281        if (anErr != noErr) {
282            return NULL;
283        }
284       
285        result = (NSString *)FSRefToPathCopy(&tempRef);
286    }
287   
288    return [result autorelease];
289}
290
291- (BOOL)isValidAlias
292{
293    return ([self fullPath] != NULL);
294}
295
296- (NSString *)description
297{
298    return [self fullPathWithDefault:@"<Invalid>"];
299}
300
301+ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias
302{
303    return [[[BDAlias alloc] initWithAliasHandle:alias] autorelease];
304}
305
306+ (BDAlias *)aliasWithData:(NSData *)data
307{
308    return [[[BDAlias alloc] initWithData:data] autorelease];
309}
310
311+ (BDAlias *)aliasWithPath:(NSString *)fullPath
312{
313    return [[[BDAlias alloc] initWithPath:fullPath] autorelease];
314}
315
316+ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath
317{
318    return [[[BDAlias alloc] initWithPath:path relativeToPath:relPath] autorelease];
319}
320
321+ (BDAlias *)aliasWithFSRef:(FSRef *)ref
322{
323    return [[[BDAlias alloc] initWithFSRef:ref] autorelease];
324}
325
326+ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
327{
328    return [[[BDAlias alloc] initWithFSRef:ref relativeToFSRef:relRef] autorelease];
329}
330
331@end