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

Last change on this file since 516 was 53, checked in by Nicholas Riley, 18 years ago

Updated for Pester 1.1a5 (very limited release).

Pester 1.1a4 was never released.

File size: 8.8 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    if (gotRef == false) {
110        return fnfErr;
111    }
112   
113    return noErr;
114}
115
116static CFStringRef FSRefToPathCopy(const FSRef *inRef)
117{
118    CFURLRef    tempURL = NULL;
119    CFStringRef result = NULL;
120   
121    if (inRef != NULL) {
122        tempURL = CFURLCreateFromFSRef(kCFAllocatorDefault, inRef);
123       
124        if (tempURL == NULL) {
125            return NULL;
126        }
127       
128        result = CFURLCopyFileSystemPath(tempURL, kCFURLPOSIXPathStyle);
129       
130        CFRelease(tempURL);
131    }
132   
133    return result;
134}
135
136
137@implementation BDAlias
138
139- (id)initWithAliasHandle:(AliasHandle)alias
140{
141    id ret = [super init];
142   
143    if (ret != nil) {
144        _alias = alias;
145    }
146   
147    return ret;
148}
149
150- (id)initWithData:(NSData *)data
151{
152    return [self initWithAliasHandle:(AliasHandle)DataToHandle((CFDataRef) data)];
153}
154
155- (id)initWithPath:(NSString *)fullPath
156{
157    OSStatus    anErr = noErr;
158    FSRef               ref;
159   
160    anErr = PathToFSRef((CFStringRef) fullPath, &ref);
161   
162    if (anErr != noErr) {
163        return nil;
164    }
165   
166    return [self initWithFSRef:&ref];;
167}
168
169- (id)initWithPath:(NSString *)path relativeToPath:(NSString *)relPath
170{
171    OSStatus    anErr = noErr;
172    FSRef               ref, relRef;
173   
174    anErr = PathToFSRef((CFStringRef) [relPath stringByAppendingPathComponent:path],
175                        &ref);
176   
177    if (anErr != noErr) {
178        return nil;
179    }
180   
181    anErr = PathToFSRef((CFStringRef) relPath, &relRef);
182   
183    if (anErr != noErr) {
184        return nil;
185    }
186   
187    return [self initWithFSRef:&ref relativeToFSRef:&relRef];
188}
189
190- (id)initWithFSRef:(FSRef *)ref
191{
192    return [self initWithFSRef:ref relativeToFSRef:NULL];
193}
194
195- (id)initWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
196{
197    OSStatus    anErr = noErr;
198    AliasHandle alias = NULL;
199   
200    anErr = FSNewAlias(relRef, ref, &alias);
201   
202    if (anErr != noErr) {
203        return nil;
204    }
205   
206    return [self initWithAliasHandle:alias];
207}
208
209- (void)dealloc
210{
211    if (_alias != NULL) {
212        DisposeHandle((Handle) _alias);
213        _alias = NULL;
214    }
215   
216    [super dealloc];
217}
218
219- (AliasHandle)alias
220{
221    return _alias;
222}
223
224- (void)setAlias:(AliasHandle)newAlias
225{
226    if (_alias != NULL) {
227        DisposeHandle((Handle) _alias);
228    }
229   
230    _alias = newAlias;
231}
232
233- (NSData *)aliasData
234{
235    NSData *result;
236   
237    result = (NSData *)HandleToData((Handle) _alias);
238   
239    return [result autorelease];
240}
241
242- (void)setAliasData:(NSData *)newAliasData
243{
244    [self setAlias:(AliasHandle) DataToHandle((CFDataRef) newAliasData)];
245}
246
247- (NSString *)displayNameWithKindString:(NSString **)outKindString;
248{
249    AliasHandle alias = [self alias];
250    FSRef ref;
251    Boolean wasChanged;
252    CFStringRef name;
253
254    if (alias == NULL) return nil;
255    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return nil;
256
257    if (LSCopyDisplayNameForRef(&ref, &name) != noErr) return nil;
258    [(NSString *)name autorelease];
259
260    if (outKindString != NULL) {
261        if (LSCopyKindStringForRef(&ref, (CFStringRef *)outKindString) != noErr) return nil;
262        [*outKindString autorelease];
263    }
264
265    return (NSString *)name;
266}
267
268- (NSString *)fullPath
269{
270    return [self fullPathRelativeToPath:nil];
271}
272
273- (NSString *)fullPathRelativeToPath:(NSString *)relPath
274{
275    OSStatus    anErr = noErr;
276    FSRef       relPathRef;
277    FSRef       tempRef;
278    NSString    *result = nil;
279    Boolean     wasChanged;
280   
281    if (_alias != NULL) {
282        if (relPath != nil) {
283            anErr = PathToFSRef((CFStringRef)relPath, &relPathRef);
284           
285            if (anErr != noErr) {
286                return NULL;
287            }
288           
289            anErr = FSResolveAlias(&relPathRef, _alias, &tempRef, &wasChanged);
290        } else {
291            anErr = FSResolveAlias(NULL, _alias, &tempRef, &wasChanged);
292        }
293       
294        if (anErr != noErr) {
295            return NULL;
296        }
297       
298        result = (NSString *)FSRefToPathCopy(&tempRef);
299    }
300   
301    return [result autorelease];
302}
303
304- (BOOL)aliasIsEqual:(AliasHandle)otherAlias;
305{
306    AliasHandle alias = [self alias];
307    FSRef ref, otherRef;
308    Boolean wasChanged;
309
310    if (alias == otherAlias) return YES;
311    if (alias == NULL || otherAlias == NULL) return NO;
312    if (FSResolveAlias(NULL, alias, &ref, &wasChanged) != noErr) return NO;
313    if (FSResolveAlias(NULL, otherAlias, &otherRef, &wasChanged) != noErr) return NO;
314    return (FSCompareFSRefs(&ref, &otherRef) == noErr);
315}
316
317- (BOOL)aliasDataIsEqual:(NSData *)data;
318{
319    AliasHandle otherAlias;
320    const UInt8 *aliasPtr = CFDataGetBytePtr((CFDataRef)data);
321    BOOL result;
322    if (aliasPtr == NULL) {
323        otherAlias = (AliasHandle)DataToHandle((CFDataRef)data);
324    } else {
325        otherAlias = (AliasHandle)&aliasPtr;
326    }
327    result = [self aliasIsEqual: otherAlias];
328    if (aliasPtr == NULL) DisposeHandle((Handle)otherAlias);
329    return result;
330}
331
332- (BOOL)isEqual:(id)object;
333{
334    if (![object isKindOfClass: [BDAlias class]]) return NO;
335    return [self aliasIsEqual: [object alias]];
336}
337
338+ (BDAlias *)aliasWithAliasHandle:(AliasHandle)alias
339{
340    return [[[BDAlias alloc] initWithAliasHandle:alias] autorelease];
341}
342
343+ (BDAlias *)aliasWithData:(NSData *)data
344{
345    return [[[BDAlias alloc] initWithData:data] autorelease];
346}
347
348+ (BDAlias *)aliasWithPath:(NSString *)fullPath
349{
350    return [[[BDAlias alloc] initWithPath:fullPath] autorelease];
351}
352
353+ (BDAlias *)aliasWithPath:(NSString *)path relativeToPath:(NSString *)relPath
354{
355    return [[[BDAlias alloc] initWithPath:path relativeToPath:relPath] autorelease];
356}
357
358+ (BDAlias *)aliasWithFSRef:(FSRef *)ref
359{
360    return [[[BDAlias alloc] initWithFSRef:ref] autorelease];
361}
362
363+ (BDAlias *)aliasWithFSRef:(FSRef *)ref relativeToFSRef:(FSRef *)relRef
364{
365    return [[[BDAlias alloc] initWithFSRef:ref relativeToFSRef:relRef] autorelease];
366}
367
368@end
Note: See TracBrowser for help on using the repository browser.