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
|