source: trunk/Cocoa/Pester/Source/BDAlias.m @ 557

Last change on this file since 557 was 557, checked in by Nicholas Riley, 10 years ago

Fix leak in BDAlias.

File size: 8.6 KB
Line 
1/*
2    Copyright (c) 2001, 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 *)displayNameWithKindString:(NSString **)outKindString;
250{
251    AliasHandle alias = [self alias];
252    FSRef ref;
253    Boolean wasChanged;
254    CFStringRef name;
255
256    if (alias == NULL) return nil;
257    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return nil;
258
259    if (LSCopyDisplayNameForRef(&ref, &name) != noErr) return nil;
260    [(NSString *)name autorelease];
261
262    if (outKindString != NULL) {
263        if (LSCopyKindStringForRef(&ref, (CFStringRef *)outKindString) != noErr) return nil;
264        [*outKindString autorelease];
265    }
266
267    return (NSString *)name;
268}
269
270- (NSString *)fullPath
271{
272    return [self fullPathRelativeToPath:nil];
273}
274
275- (NSString *)fullPathRelativeToPath:(NSString *)relPath
276{
277    OSStatus    anErr = noErr;
278    FSRef       relPathRef;
279    FSRef       tempRef;
280    NSString    *result = nil;
281    Boolean     wasChanged;
282   
283    if (_alias != NULL) {
284        if (relPath != nil) {
285            anErr = PathToFSRef((CFStringRef)relPath, &relPathRef);
286           
287            if (anErr != noErr) {
288                return NULL;
289            }
290           
291            anErr = FSResolveAlias(&relPathRef, _alias, &tempRef, &wasChanged);
292        } else {
293            anErr = FSResolveAlias(NULL, _alias, &tempRef, &wasChanged);
294        }
295       
296        if (anErr != noErr) {
297            return NULL;
298        }
299       
300        result = (NSString *)FSRefToPathCopy(&tempRef);
301    }
302   
303    return [result autorelease];
304}
305
306- (BOOL)aliasIsEqual:(AliasHandle)otherAlias;
307{
308    AliasHandle alias = [self alias];
309    FSRef ref, otherRef;
310    Boolean wasChanged;
311
312    if (alias == otherAlias) return YES;
313    if (alias == NULL || otherAlias == NULL) return NO;
314    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return NO;
315    if (FSResolveAlias(NULL, otherAlias, &otherRef, &wasChanged) != noErr) return NO;
316    return (FSCompareFSRefs(&ref, &otherRef) == noErr);
317}
318
319- (BOOL)aliasDataIsEqual:(NSData *)data;
320{
321    BOOL result;
322    AliasHandle otherAlias = (AliasHandle)DataToHandle((CFDataRef)data);
323    result = [self aliasIsEqual: otherAlias];
324    DisposeHandle((Handle)otherAlias);
325    return result;
326}
327
328- (BOOL)isEqual:(id)object;
329{
330    if (![object isKindOfClass: [BDAlias class]]) return NO;
331    return [self aliasIsEqual: [object alias]];
332}
333
334+ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias
335{
336    return [[[BDAlias alloc] initWithAliasHandle:alias] autorelease];
337}
338
339+ (BDAlias *)aliasWithData:(NSData *)data
340{
341    return [[[BDAlias alloc] initWithData:data] autorelease];
342}
343
344+ (BDAlias *)aliasWithPath:(NSString *)fullPath
345{
346    return [[[BDAlias alloc] initWithPath:fullPath] autorelease];
347}
348
349+ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath
350{
351    return [[[BDAlias alloc] initWithPath:path relativeToPath:relPath] autorelease];
352}
353
354+ (BDAlias *)aliasWithFSRef:(FSRef *)ref
355{
356    return [[[BDAlias alloc] initWithFSRef:ref] autorelease];
357}
358
359+ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
360{
361    return [[[BDAlias alloc] initWithFSRef:ref relativeToFSRef:relRef] autorelease];
362}
363
364@end
Note: See TracBrowser for help on using the repository browser.