2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include <NGExtensions/NGCustomFileManager.h>
27 NSString *absolutePath;
29 NGCustomFileManagerInfo *info;
33 @interface NGCustomFileManager(Helpers)
34 - (NGCustomFMPath)_resolvePath:(NSString *)_path;
35 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path;
36 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler;
37 - (id)_do:(SEL)_sel onPath:(NSString *)_path;
40 @implementation NGCustomFileManager
43 return [super version] + 0 /* v0 */;
46 NSAssert2([super version] == 0,
47 @"invalid superclass (%@) version %i !",
48 NSStringFromClass([self superclass]), [super version]);
53 - (NSString *)makeAbsolutePath:(NSString *)_path {
54 if ([_path isAbsolutePath])
57 return [[self currentDirectoryPath] stringByAppendingPathComponent:_path];
60 - (NGCustomFileManagerInfo *)fileManagerInfoForPath:(NSString *)_path {
66 - (NGCustomFMPath)_resolvePath:(NSString *)_path {
70 p.absolutePath = [self makeAbsolutePath:_path];
71 p.info = [self fileManagerInfoForPath:_path];
72 p.path = [p.info rewriteAbsolutePath:p.absolutePath];
73 p.fileManager = [p.info fileManager];
77 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path {
79 BOOL (*op)(id,SEL,NSString *);
81 if (_sel == NULL) return NO;
82 p = [self _resolvePath:_path];
83 if ((_path = p.path) == nil) return NO;
84 if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
86 return op(p.fileManager, _sel, _path);
88 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler {
90 BOOL (*op)(id,SEL,NSString *,id);
92 if (_sel == NULL) return NO;
93 p = [self _resolvePath:_path];
94 if ((_path = p.path) == nil) return NO;
95 if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
97 return op(p.fileManager, _sel, _path, _handler);
99 - (id)_do:(SEL)_sel onPath:(NSString *)_path {
101 id (*op)(id,SEL,NSString *);
103 if (_sel == NULL) return NO;
104 p = [self _resolvePath:_path];
105 if ((_path = p.path) == nil) return NO;
106 if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
108 return op(p.fileManager, _sel, _path);
111 /* directory operations */
113 - (BOOL)changeCurrentDirectoryPath:(NSString *)_path {
115 if ((_path = [self makeAbsolutePath:_path]) == nil) return NO;
117 if (![self fileExistsAtPath:_path isDirectory:&isDir]) return NO;
118 if (!isDir) return NO;
120 ASSIGNCOPY(self->cwd, _path);
123 - (NSString *)currentDirectoryPath {
127 - (BOOL)createDirectoryAtPath:(NSString *)_path
128 attributes:(NSDictionary *)_ats
131 p = [self _resolvePath:_path];
132 if (p.path == nil) return NO;
134 return [p.fileManager createDirectoryAtPath:p.path attributes:_ats];
137 /* file operations */
139 - (BOOL)copyPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
140 NGCustomFileManagerInfo *sinfo, *dinfo;
142 if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
143 if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
144 if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
145 if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
146 _s = [sinfo rewriteAbsolutePath:_s];
147 _d = [dinfo rewriteAbsolutePath:_d];
149 if ([sinfo isEqual:dinfo]) /* same filemanager */
150 return [[sinfo fileManager] copyPath:_s toPath:_d handler:_handler];
152 /* operation between different filemanagers ... */
156 - (BOOL)movePath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
157 NGCustomFileManagerInfo *sinfo, *dinfo;
159 if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
160 if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
161 if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
162 if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
163 _s = [sinfo rewriteAbsolutePath:_s];
164 _d = [dinfo rewriteAbsolutePath:_d];
166 if ([sinfo isEqual:dinfo]) /* same filemanager */
167 return [[sinfo fileManager] movePath:_s toPath:_d handler:_handler];
169 /* operation between different filemanagers ... */
173 - (BOOL)linkPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
174 NGCustomFileManagerInfo *sinfo, *dinfo;
176 if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
177 if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
178 if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
179 if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
180 _s = [sinfo rewriteAbsolutePath:_s];
181 _d = [dinfo rewriteAbsolutePath:_d];
183 if ([sinfo isEqual:dinfo]) /* same filemanager */
184 return [[sinfo fileManager] linkPath:_s toPath:_d handler:_handler];
186 /* operation between different filemanagers ... */
190 - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_handler {
191 return [self _boolDo:_cmd onPath:_path handler:_handler];
194 - (BOOL)createFileAtPath:(NSString *)_path contents:(NSData *)_contents
195 attributes:(NSDictionary *)_attributes
198 p = [self _resolvePath:_path];
199 if (p.path == nil) return NO;
201 return [p.fileManager
202 createFileAtPath:p.path
204 attributes:_attributes];
207 /* getting and comparing file contents */
209 - (NSData *)contentsAtPath:(NSString *)_path {
210 return [self _do:_cmd onPath:_path];
213 - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2 {
214 NGCustomFileManagerInfo *info1, *info2;
216 if ((_path1 = [self makeAbsolutePath:_path1]) == nil) return NO;
217 if ((_path2 = [self makeAbsolutePath:_path2]) == nil) return NO;
218 if ((info1 = [self fileManagerInfoForPath:_path1]) == nil) return NO;
219 if ((info2 = [self fileManagerInfoForPath:_path2]) == nil) return NO;
220 _path1 = [info1 rewriteAbsolutePath:_path1];
221 _path2 = [info2 rewriteAbsolutePath:_path2];
223 if ([info1 isEqual:info2]) /* same filemanager */
224 return [[info1 fileManager] contentsEqualAtPath:_path1 andPath:_path2];
226 /* operation between different filemanagers ... */
230 /* determining access to files */
232 - (BOOL)fileExistsAtPath:(NSString *)_path {
233 return [self _boolDo:_cmd onPath:_path];
235 - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDirectory {
237 p = [self _resolvePath:_path];
238 if (p.path == nil) return NO;
240 return [p.fileManager fileExistsAtPath:p.path isDirectory:_isDirectory];
242 - (BOOL)isReadableFileAtPath:(NSString *)_path {
243 return [self _boolDo:_cmd onPath:_path];
245 - (BOOL)isWritableFileAtPath:(NSString *)_path {
246 return [self _boolDo:_cmd onPath:_path];
248 - (BOOL)isExecutableFileAtPath:(NSString *)_path {
249 return [self _boolDo:_cmd onPath:_path];
251 - (BOOL)isDeletableFileAtPath:(NSString *)_path {
252 return [self _boolDo:_cmd onPath:_path];
255 /* Getting and setting attributes */
257 - (NSDictionary *)fileAttributesAtPath:(NSString *)_p traverseLink:(BOOL)_flag{
259 p = [self _resolvePath:_p];
260 if (p.path == nil) return NO;
262 /* special link handling required ??? */
263 return [p.fileManager fileAttributesAtPath:p.path traverseLink:_flag];
266 - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_p {
267 return [self _do:_cmd onPath:_p];
270 - (BOOL)changeFileAttributes:(NSDictionary *)_attributes atPath:(NSString *)_p{
272 p = [self _resolvePath:_p];
273 if (p.path == nil) return NO;
275 return [p.fileManager changeFileAttributes:_attributes atPath:p.path];
278 /* discovering directory contents */
280 - (NSArray *)directoryContentsAtPath:(NSString *)_path {
281 /* this returns relative path's, can be passed back */
282 return [self _do:_cmd onPath:_path];
285 - (NSDirectoryEnumerator *)enumeratorAtPath:(NSString *)_path {
286 /* this needs to be wrapped ! */
290 - (NSArray *)subpathsAtPath:(NSString *)_path {
291 /* this returns relative path's, can be passed back */
292 return [self _do:_cmd onPath:_path];
295 /* symbolic-link operations */
297 - (BOOL)createSymbolicLinkAtPath:(NSString *)_p pathContent:(NSString *)_dpath{
298 /* should that process the link-path somehow ??? */
300 p = [self _resolvePath:_p];
301 if (p.path == nil) return NO;
303 return [p.fileManager createSymbolicLinkAtPath:p.path pathContent:_dpath];
305 - (NSString *)pathContentOfSymbolicLinkAtPath:(NSString *)_path {
306 /* should that process the link-path somehow ??? */
307 return [self _do:_cmd onPath:_path];
312 - (BOOL)supportsVersioningAtPath:(NSString *)_path {
313 return [self _boolDo:_cmd onPath:_path];
315 - (BOOL)supportsLockingAtPath:(NSString *)_path {
316 return [self _boolDo:_cmd onPath:_path];
318 - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path {
319 return [self _boolDo:_cmd onPath:_path];
322 - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path {
324 p = [self _resolvePath:_path];
325 if (p.path == nil) return NO;
327 return [p.fileManager supportsFeature:_featureURI atPath:p.path];
332 - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path {
334 p = [self _resolvePath:_path];
335 if (p.path == nil) return NO;
337 return [p.fileManager writeContents:_content atPath:p.path];
342 - (EOGlobalID *)globalIDForPath:(NSString *)_path {
343 NGCustomFileManagerInfo *info;
344 if ((_path = [self makeAbsolutePath:_path]) == nil) return NO;
345 if ((info = [self fileManagerInfoForPath:_path]) == nil) return NO;
347 if (![info supportsGlobalIDs])
350 if ((_path = [info rewriteAbsolutePath:_path]) == nil)
353 return [[info fileManager] globalIDForPath:_path];
356 - (NSString *)pathForGlobalID:(EOGlobalID *)_gid {
362 - (BOOL)supportsTrashFolderAtPath:(NSString *)_path {
363 return [self _boolDo:_cmd onPath:_path];
365 - (NSString *)trashFolderForPath:(NSString *)_path {
369 @end /* NGCustomFileManager */
371 @implementation NGCustomFileManager(NGFileManagerVersioning)
375 - (BOOL)checkoutFileAtPath:(NSString *)_path handler:(id)_handler {
376 return [self _boolDo:_cmd onPath:_path handler:_handler];
378 - (BOOL)releaseFileAtPath:(NSString *)_path handler:(id)_handler {
379 return [self _boolDo:_cmd onPath:_path handler:_handler];
381 - (BOOL)rejectFileAtPath:(NSString *)_path handler:(id)_handler {
382 return [self _boolDo:_cmd onPath:_path handler:_handler];
384 - (BOOL)checkoutFileAtPath:(NSString *)_path version:(NSString *)_version
388 p = [self _resolvePath:_path];
389 if (p.path == nil) return NO;
391 return [p.fileManager
392 checkoutFileAtPath:p.path version:_version handler:_handler];
395 /* versioning data */
397 - (NSString *)lastVersionAtPath:(NSString *)_path {
398 return [self _do:_cmd onPath:_path];
400 - (NSArray *)versionsAtPath:(NSString *)_path {
401 return [self _do:_cmd onPath:_path];
404 - (NSData *)contentsAtPath:(NSString *)_path version:(NSString *)_version {
406 p = [self _resolvePath:_path];
407 if (p.path == nil) return NO;
409 return [p.fileManager contentsAtPath:p.path version:_version];
412 - (NSDictionary *)fileAttributesAtPath:(NSString *)_path
413 traverseLink:(BOOL)_followLink
414 version:(NSString *)_version
417 p = [self _resolvePath:_path];
418 if (p.path == nil) return NO;
420 /* do something special to symlink ??? */
422 return [p.fileManager
423 fileAttributesAtPath:p.path
424 traverseLink:_followLink
428 @end /* NGCustomFileManager(NGFileManagerVersioning) */
430 @implementation NGCustomFileManager(NGFileManagerLocking)
432 - (BOOL)lockFileAtPath:(NSString *)_path handler:(id)_handler {
433 return [self _boolDo:_cmd onPath:_path handler:_handler];
435 - (BOOL)unlockFileAtPath:(NSString *)_path handler:(id)_handler {
436 return [self _boolDo:_cmd onPath:_path handler:_handler];
438 - (BOOL)isFileLockedAtPath:(NSString *)_path {
439 return [self _boolDo:_cmd onPath:_path];
444 - (BOOL)isLockableFileAtPath:(NSString *)_path {
445 return [self _boolDo:_cmd onPath:_path];
447 - (BOOL)isUnlockableFileAtPath:(NSString *)_path {
448 return [self _boolDo:_cmd onPath:_path];
451 @end /* NGCustomFileManager(NGFileManagerLocking) */
453 @implementation NGCustomFileManager(NGFileManagerDataSources)
455 /* datasources (work on folders) */
457 - (EODataSource *)dataSourceAtPath:(NSString *)_path {
458 return [self _do:_cmd onPath:_path];
461 - (EODataSource *)dataSource {
462 return [self dataSourceAtPath:[self currentDirectoryPath]];
465 @end /* NGCustomFileManager(NGFileManagerDataSources) */
467 @implementation NGCustomFileManagerInfo
469 - (id)initWithCustomFileManager:(NGCustomFileManager *)_master
470 fileManager:(id<NGFileManager,NSObject>)_fm
472 self->master = _master;
473 self->fileManager = [_fm retain];
477 return [self initWithCustomFileManager:nil fileManager:nil];
481 [self->fileManager release];
485 - (void)resetMaster {
491 - (NGCustomFileManager *)master {
494 - (id<NGFileManager,NSObject>)fileManager {
495 return self->fileManager;
500 - (NSString *)rewriteAbsolutePath:(NSString *)_path {
506 - (BOOL)supportsGlobalIDs {
507 return [self->fileManager respondsToSelector:@selector(globalIDForPath:)];
510 @end /* NGCustomFileManagerInfo */