Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 855 lines (699 sloc) 28.625 kb
720b0e7 @uliwitness Added licensing information to the source files.
uliwitness authored
1 //
2 // UKDirectoryEnumerator.m
3 // Filie
4 //
5 // Created by Uli Kusterer on 2004-04-15
6 // Copyright 2004 Uli Kusterer.
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
26 //
dc5be1c Initial check-in.
uli authored
27
28 // -----------------------------------------------------------------------------
29 // Headers:
30 // -----------------------------------------------------------------------------
31
32 #import "UKDirectoryEnumerator.h"
33 #import "NSString+CarbonUtilities.h"
34
35
36 // -----------------------------------------------------------------------------
37 // Prototypes:
38 // -----------------------------------------------------------------------------
39
40 NSDictionary* UKDictionaryFromFSCatInfo( FSCatalogInfo* currInfo, FSCatalogInfoBitmap whichInfo );
41 void UKFSCatInfoFromDictionary( NSDictionary* attrs, FSCatalogInfo* currInfo, FSCatalogInfoBitmap* whichInfo );
42
43
44 @implementation UKDirectoryEnumerator
45
46 #if UKDE_ALLOW_ENUMERATORWITHPATH
47 +(id) enumeratorWithPath: (NSString*)fpath
48 {
49 return [[self class] enumeratorAtPath: fpath];
50 }
51
52 +(id) enumeratorWithPath: (NSString*)fpath cacheSize: (ItemCount)n
53 {
54 return [[self class] enumeratorAtPath: fpath cacheSize: n];
55 }
56 #endif
57
58
59 +(id) enumeratorAtPath: (NSString*)fpath
60 {
61 return [[[[self class] alloc] initWithPath: fpath] autorelease];
62 }
63
64 +(id) enumeratorAtPath: (NSString*)fpath cacheSize: (ItemCount)n
65 {
66 return [[[[self class] alloc] initWithPath: fpath cacheSize: n] autorelease];
67 }
68
69
70 // -----------------------------------------------------------------------------
71 // initWithPath:
72 // Convenience initializer. Uses a default cache size.
73 //
74 // REVISIONS:
75 // 2004-11-11 UK Documented.
76 // -----------------------------------------------------------------------------
77
78 -(id) initWithPath: (NSString*)fpath
79 {
80 return [self initWithPath: fpath cacheSize: UKDirectoryEnumeratorCacheSize];
81 }
82
83
84 // -----------------------------------------------------------------------------
85 // initWithFSRef:cacheSize:
86 // Designated initializer. Opens our FSIterator and initializes our
87 // cache.
88 //
89 // REVISIONS:
90 // 2006-08-22 UK Extracted from initWithPath:cacheSize:.
91 // -----------------------------------------------------------------------------
92
93 -(id) initWithFSRef: (FSRef)theFile cacheSize: (ItemCount)n desiredInfo: (FSCatalogInfoBitmap)desInfo
94 {
95 self = [super init];
96 if( self )
97 {
98 FSRef container;
99 OSErr err = noErr;
100
101 whichInfo = desInfo;
102
103 if( (err = FSOpenIterator( &theFile, kFSIterateFlat, &iterator )) != noErr )
104 {
105 NSLog(@"UKDirectoryEnumerator::initWithFSRef: - MacOS Error ID= %d",err);
106 [self autorelease];
107 return nil;
108 }
109
110 NSString* fpath = [NSString stringWithFSRef: &container]; // In case it's a link or an alias that got resolved.
111 prefixlen = [fpath length] +(([fpath characterAtIndex: [fpath length] -1] == '/') ? 0 : 1);
112
113 [self setCacheSize: n];
114 }
115
116 return self;
117 }
118
119
120 // -----------------------------------------------------------------------------
121 // initWithPath:cacheSize:
122 // Opens our FSIterator and initializes our cache.
123 //
124 // REVISIONS:
125 // 2006-08-22 UK Moved code to init from FSRef into a separate method.
126 // 2004-11-11 UK Documented.
127 // -----------------------------------------------------------------------------
128
129 -(id) initWithPath: (NSString*)fpath cacheSize: (ItemCount)n
130 {
131 FSRef container;
132 if( ![fpath getFSRef: &container] )
133 {
134 self = [super init];
135 NSLog(@"UKDirectoryEnumerator::initWithPath: Can't get an FSRef for the specified path.");
136 [self autorelease];
137 return nil;
138 }
139
140 self = [self initWithFSRef: container cacheSize: n desiredInfo: kFSCatInfoNone];
141
142 return self;
143 }
144
145
146 // -----------------------------------------------------------------------------
147 // dealloc:
148 // Close FSIterator that we wrap with this object.
149 //
150 // REVISIONS:
151 // 2005-10-15 UK Made this release infoCache. Thanks Nicholas Jitkoff!
152 // 2004-11-11 UK Documented.
153 // -----------------------------------------------------------------------------
154
155 -(void) dealloc
156 {
157 if( cache )
158 free( cache );
159
160 if( infoCache )
161 free( infoCache );
162
163 if( iterator != NULL )
164 FSCloseIterator( iterator );
165
166 [super dealloc];
167 }
168
169
170 // -----------------------------------------------------------------------------
171 // iterator:
172 // Let those Carbon fans manually mess with the FSIterator if they have
173 // a need to.
174 //
175 // REVISIONS:
176 // 2004-11-11 UK Documented.
177 // -----------------------------------------------------------------------------
178
179 -(FSIterator) iterator
180 {
181 return iterator;
182 }
183
184
185 // -----------------------------------------------------------------------------
186 // nextObjectFSRef:
187 // Fetch the next file FSRef from the cache. If the cache is empty,
188 // this will get the next batch of FSRefs into the cache using the Carbon
189 // FSGetCatalogInfoBulk call, and also cache their file info.
190 //
191 // REVISIONS:
192 // 2006-08-22 UK Extracted this code from nextObjectFullPath:.
193 // -----------------------------------------------------------------------------
194
195 -(FSRef*) nextObjectFSRef
196 {
197 if( currIndex >= foundItems )
198 {
199 OSErr err = FSGetCatalogInfoBulk( iterator, cacheSize, &foundItems,
200 NULL, whichInfo, infoCache,
201 cache, (FSSpec*) NULL,
202 (HFSUniStr255*) NULL); // TODO: We could use this param to get the names for a faster -nextObject implementation.
203 if( err != noErr && err != errFSNoMoreItems )
204 {
205 NSLog(@"UKDirectoryEnumerator::nextObjectFSRef - MacOS Error ID= %d",err);
206 return nil;
207 }
208
209 currIndex = 0;
210 if( foundItems == 0 )
211 {
212 if( err != errFSNoMoreItems ) // No need to show error if we're just at end of list.
213 NSLog(@"UKDirectoryEnumerator::nextObjectFSRef - FSCatalogInfoBulk returned 0 items, but not errFSNoMoreItems.");
214 return nil;
215 }
216 }
217
218 return &(cache[currIndex++]);
219 }
220
221
222 // -----------------------------------------------------------------------------
223 // nextObjectFullPath:
224 // Fetch the next file path from the cache. The Cache contains FSRefs, so
225 // this will convert the FSRef into an NSString. If the cache is empty,
226 // -nextObjectFSRef will transparently recache the next batch.
227 //
228 // REVISIONS:
229 // 2006-08-22 UK Extracted most of the code in this method into
230 // -nextObjectFSRef.
231 // 2004-11-11 UK Documented.
232 // -----------------------------------------------------------------------------
233
234 -(id) nextObjectFullPath
235 {
236 return [NSString stringWithFSRef: [self nextObjectFSRef]]; // stringWithFSRef returns NIL when it gets a NIL FSRef.
237 }
238
239
240 // -----------------------------------------------------------------------------
241 // nextObject:
242 // Fetch the next file name from the cache. This is made to work the same
243 // way as NSDirectoryEnumerator, and thus only returns the filenames. If
244 // you want the absolute pathname, use nextObjectFullPath.
245 //
246 // REVISIONS:
247 // 2006-08-22 UK Changed this to call nextObjectFSRef directly instead
248 // of going through -nextObjectFullPath.
249 // 2004-11-11 UK Documented.
250 // -----------------------------------------------------------------------------
251
252 -(id) nextObject
253 {
254 NSString* fname = [NSString stringWithFSRef: [self nextObjectFSRef]]; // stringWithFSRef returns NIL when it gets a NIL FSRef.
255 if( !fname )
256 return nil;
257 return [fname substringWithRange: NSMakeRange(prefixlen,[fname length] -prefixlen)]; // Remove the prefix (parent folder) from this path to make it relative.
258 }
259
260
261 // -----------------------------------------------------------------------------
262 // cacheExhausted:
263 // Tells you whether the next call to nextObject will cause a reload of the
264 // cache. You usually don't need this, but sometimes it's useful for
265 // deciding when to update progress information. If there will be a short
266 // pause while the File Manager caches some more FSRefs, you might as well
267 // accept the overhead of drawing new status info to the screen.
268 //
269 // REVISIONS:
270 // 2004-11-11 UK Documented.
271 // -----------------------------------------------------------------------------
272
273 -(BOOL) cacheExhausted
274 {
275 return( currIndex >= foundItems );
276 }
277
278
279 // -----------------------------------------------------------------------------
280 // fileAttributes:
281 // This is basically the same as NSDirectoryEnumerator's fileAttributes
282 // method. However, what you get here depends on what flags you specified
283 // to setDesiredInfo:, which defaults to kFSCatInfoNone, which means you
284 // get an empty dictionary here if you don't explicitly ask for info.
285 //
286 // Depending on what you pass to setDesiredInfo:, you can even get
287 // additional info that you wouldn't get from an NSDirectoryEnumerator.
288 // In particular, since we're using Carbon under the hood, we get all the
289 // nice info the Finder knows, but other Cocoa apps don't.
290 //
291 // This is an expensive call. If you can, use others like isInvisible or
292 // isDirectory.
293 //
294 // REVISIONS:
295 // 2005-07-03 UK Extracted CatInfo -> Dictionary code into separate
296 // function UKDictionaryFromFSCatInfo().
297 // 2004-11-11 UK Documented.
298 // -----------------------------------------------------------------------------
299
300 #define UK_BTST(f,m) (((f) & (m)) == (m)) // Shorthand bit-test macro.
301
302 -(NSDictionary*) fileAttributes
303 {
304 if( infoCache == NULL )
305 return [NSMutableDictionary dictionary];
306
307 FSCatalogInfo* currInfo = &(infoCache[currIndex -1]);
308
309 return UKDictionaryFromFSCatInfo( currInfo, whichInfo );
310 }
311
312
313 // -----------------------------------------------------------------------------
314 // isInvisible:
315 // If you passed the kFSCatInfoFinderInfo flag to setDesiredInfo:, this
316 // will return the value of the Finder's kIsInvisible file flag. Otherwise
317 // this will ruthlessly claim the file was visible.
318 //
319 // This will *not* do any other checks, like whether the file name starts
320 // with a period.
321 //
322 // REVISIONS:
323 // 2004-11-11 UK Documented.
324 // -----------------------------------------------------------------------------
325
326 -(BOOL) isInvisible
327 {
328 FSCatalogInfo* currInfo = &(infoCache[currIndex -1]);
329
330 if( UK_BTST(whichInfo, kFSCatInfoFinderInfo) )
331 {
332 FileInfo* fInfo = (FileInfo*) currInfo->finderInfo;
333 return UK_BTST(fInfo->finderFlags, kIsInvisible);
334 }
335 else
336 return NO;
337 }
338
339
340 -(BOOL) shouldBeDisplayed
341 {
342 return !([self isInvisible] || ([[[NSString stringWithFSRef: &(cache[currIndex -1]) ] lastPathComponent] characterAtIndex: 0] == '.'));
343 }
344
345
346 // -----------------------------------------------------------------------------
347 // isDirectory:
348 // If you passed the kFSCatInfoNodeFlags flag to setDesiredInfo:, this
349 // will tell you whether an item is a directory (aka folder) or not.
350 // Otherwise this will ruthlessly claim it was a file.
351 //
352 // REVISIONS:
353 // 2004-11-11 UK Documented.
354 // -----------------------------------------------------------------------------
355
356 -(BOOL) isDirectory
357 {
358 FSCatalogInfo* currInfo = &(infoCache[currIndex -1]);
359
360 if( UK_BTST(whichInfo, kFSCatInfoNodeFlags) )
361 return UK_BTST(currInfo->nodeFlags, kFSNodeIsDirectoryMask);
362 else
363 return NO;
364 }
365
366
367 // -----------------------------------------------------------------------------
368 // setDesiredInfo:
369 // Takes a bit field of or-ed together FSCatalogInfoBitmap flags that
370 // control what information will be collected about files. You can then
371 // query this information using the fileAttributes, isInvisible and
372 // isDirectory methods.
373 //
374 // This only works *before* making your first call to nextObject or the
375 // likes.
376 //
377 // FSCatalogInfoBitmap and the associated flags are defined in
378 // <Carbon/Files.h>.
379 //
380 // REVISIONS:
381 // 2004-11-11 UK Documented.
382 // -----------------------------------------------------------------------------
383
384 -(void) setDesiredInfo: (FSCatalogInfoBitmap)n
385 {
386 if( whichInfo != n )
387 {
388 whichInfo = n;
389
390 if( whichInfo == kFSCatInfoNone && infoCache != NULL )
391 {
392 free( infoCache );
393 infoCache = NULL;
394 }
395 else if( whichInfo != kFSCatInfoNone && infoCache == NULL )
396 {
397 infoCache = malloc( sizeof(FSCatalogInfo) * cacheSize );
398 if( cache == NULL )
399 whichInfo = kFSCatInfoNone;
400 }
401 }
402 }
403
404
405 // -----------------------------------------------------------------------------
406 // desiredInfo:
407 // Returns the flags set using setDesiredInfo:. If you didn't call that,
408 // you'll probably get the default kFSCatalogInfoNone.
409 //
410 // REVISIONS:
411 // 2004-11-11 UK Documented.
412 // -----------------------------------------------------------------------------
413
414 -(FSCatalogInfoBitmap) desiredInfo
415 {
416 return whichInfo;
417 }
418
419 #if UKDE_ALLOW_SETWHICHINFO
420 // -----------------------------------------------------------------------------
421 // setWhichInfo: and whichInfo: *DEPRECATED*
422 // -----------------------------------------------------------------------------
423
424 -(void) setWhichInfo: (FSCatalogInfoBitmap)n
425 {
426 [self setDesiredInfo: n];
427 }
428
429 -(FSCatalogInfoBitmap) whichInfo
430 {
431 return [self desiredInfo];
432 }
433 #endif
434
435
436 // -----------------------------------------------------------------------------
437 // setCacheSize:
438 // Controls the size (in number of files) of the cache used when getting
439 // the files. The file list is retrieved in batches of that many files,
440 // and -nextObject will automatically fetch the next item from the cache
441 // and load the next batch into the cache as needed.
442 //
443 // Note that this destroys any currently cached items. So only call this
444 // before your first call to -nextObject or when -cacheExhausted is YES.
445 //
446 // REVISIONS:
447 // 2004-11-11 UK Documented.
448 // -----------------------------------------------------------------------------
449
450 -(void) setCacheSize: (ItemCount)c
451 {
452 // Get rid of the old FSRef and FSCatalogInfo caches:
453 if( cache )
454 {
455 free(cache);
456 cache = NULL;
457 }
458
459 if( infoCache )
460 {
461 free(infoCache);
462 infoCache = NULL;
463 }
464
465 // Allocate new caches of the requested size:
466 cache = malloc( sizeof(FSRef) * c );
467 if( cache == NULL )
468 cacheSize = 0;
469 else
470 cacheSize = c;
471
472 if( whichInfo != kFSCatInfoNone )
473 {
474 infoCache = malloc( sizeof(FSCatalogInfo) * c );
475 if( cache == NULL )
476 whichInfo = kFSCatInfoNone;
477 }
478 }
479
480
481 // -----------------------------------------------------------------------------
482 // cacheSize:
483 // Returns the size (in number of files) of the cache used when getting
484 // the files. The file list is retrieved in batches of that many files,
485 // and -nextObject will automatically fetch the next item from the cache
486 // and load the next batch into the cache as needed.
487 //
488 // REVISIONS:
489 // 2004-11-11 UK Documented.
490 // -----------------------------------------------------------------------------
491
492 -(ItemCount) cacheSize
493 {
494 return cacheSize;
495 }
496
497 @end
498
499
500 @implementation NSFileManager (UKDirectoryEnumeratorVisibleDirectoryContents)
501
502 // -----------------------------------------------------------------------------
503 // visibleDirectoryContentsAtPath:
504 // Lists the contents of a particular directory (aka folder), removing
505 // any items that are invisible according to MacOS X conventions. Note
506 // that this will not consider "latent" invisibility. I.e. if you list the
507 // contents of an invisible folder, only the files that are themselves
508 // invisible inside it will be removed.
509 //
510 // This tries to apply the same criteria as the Finder when it comes to
511 // invisibility.
512 //
513 // REVISIONS:
514 // 2004-11-11 UK Created.
515 // -----------------------------------------------------------------------------
516
517 -(NSArray*) visibleDirectoryContentsAtPath: (NSString*)path
518 {
519 NSMutableArray* arr = [NSMutableArray array];
520 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
521 // Everything created now will be autoreleased if it isn't in arr:
522 UKDirectoryEnumerator* enny = [[[UKDirectoryEnumerator alloc] initWithPath: path] autorelease];
523 NSString* fname;
524
525 [enny setDesiredInfo: kFSCatInfoFinderInfo];
526
527 // Loop through the directory:
528 while( (fname = [enny nextObject]) )
529 {
530 if( [fname characterAtIndex: 0] == '.' ) // Unix-style invisibility?
531 continue;
532
533 if( [enny isInvisible] ) // MacOS-style invisibility?
534 continue;
535
536 [arr addObject: fname]; // File is visible and should be listed.
537 }
538
539 // Now, if we're at the file system root, consult .hidden on what other files we should hide:
540 if( [path isEqualToString: @"/"] ) // At the root level, we have some specially hidden Unix folders:
541 {
542 NSArray* hiddenList = [[NSString stringWithContentsOfFile: @"/.hidden"] componentsSeparatedByString: @"\n"];
543 [arr removeObjectsInArray: hiddenList];
544 }
545 // End of autoreleased area.
546 [pool release];
547
548 return arr;
549 }
550
551
552 -(BOOL) changeCarbonFileAttributes: (NSDictionary*)attrs atPath: (NSString*)path
553 {
554 FSCatalogInfo info;
555 FSRef fileRef;
556 OSErr err = noErr;
557 FSCatalogInfoBitmap whichInfo = kFSCatInfoNone;
558
559 if( ![path getFSRef: &fileRef] )
560 return NO;
561
562 UKFSCatInfoFromDictionary( attrs, &info, &whichInfo );
563
564 err = FSSetCatalogInfo( &fileRef, whichInfo, &info );
565 if( err != noErr )
566 NSLog( @"changeCarbonFileAttributes:atPath: FSSetCatalogInfo: MacOS Error ID=%d", err );
567
568 return( err == noErr );
569 }
570
571
572 -(NSDictionary*) carbonFileAttributesAtPath: (NSString*)path whichInfo: (FSCatalogInfoBitmap)whichInfo
573 {
574 FSCatalogInfo info;
575 FSRef fileRef;
576 OSErr err = noErr;
577
578 if( ![path getFSRef: &fileRef] )
579 return nil;
580
581 err = FSGetCatalogInfo( &fileRef, whichInfo, &info, NULL,NULL, NULL );
582 if( err != noErr )
583 return nil;
584
585 return UKDictionaryFromFSCatInfo( &info, whichInfo );
586 }
587
588
589 @end
590
591
592 NSDictionary* UKDictionaryFromFSCatInfo( FSCatalogInfo* currInfo, FSCatalogInfoBitmap whichInfo )
593 {
594 NSMutableDictionary* dict = [NSMutableDictionary dictionary];
595
596 if( UK_BTST(whichInfo, kFSCatInfoNodeFlags) )
597 {
598 [dict setObject: [NSNumber numberWithBool: UK_BTST(currInfo->nodeFlags, kFSNodeLockedMask)] forKey: UKItemIsLocked];
599 if( UK_BTST(currInfo->nodeFlags, kFSNodeIsDirectoryMask) )
600 [dict setObject: NSFileTypeDirectory forKey: NSFileType];
601 else
602 [dict setObject: NSFileTypeRegular forKey: NSFileType];
603 }
604 if( UK_BTST(whichInfo, kFSCatInfoFinderInfo) )
605 {
606 FileInfo* fInfo = (FileInfo*) currInfo->finderInfo;
607
608 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kIsInvisible)] forKey: UKItemIsInvisible];
609 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kIsAlias)] forKey: UKItemIsAlias];
610 if( UK_BTST(fInfo->finderFlags, kIsAlias) )
611 [dict setObject: NSFileTypeSymbolicLink forKey: NSFileType];
612 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kHasBundle)] forKey: UKItemHasBNDL];
613 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kNameLocked)] forKey: UKItemNameIsLocked];
614 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kIsStationery)] forKey: UKItemIsStationery];
615 [dict setObject: [NSNumber numberWithBool: UK_BTST(fInfo->finderFlags, kHasCustomIcon)] forKey: UKItemHasCustomIcon];
616 [dict setObject: [NSNumber numberWithInt: (fInfo->finderFlags & kColor) >> 1] forKey: UKLabelNumber];
617
618 [dict setObject: [NSNumber numberWithUnsignedLong: fInfo->fileType] forKey: NSFileHFSTypeCode];
619 [dict setObject: [NSNumber numberWithUnsignedLong: fInfo->fileCreator] forKey: NSFileHFSCreatorCode];
620 }
621 if( UK_BTST(whichInfo, kFSCatInfoDataSizes) )
622 {
623 [dict setObject: [NSNumber numberWithUnsignedLongLong: currInfo->dataLogicalSize] forKey: NSFileSize];
624 [dict setObject: [NSNumber numberWithUnsignedLongLong: currInfo->dataPhysicalSize] forKey: UKPhysicalFileSize];
625 }
626 if( UK_BTST(whichInfo, kFSCatInfoRsrcSizes) )
627 {
628 [dict setObject: [NSNumber numberWithUnsignedLongLong: currInfo->rsrcLogicalSize] forKey: UKLogicalResFileSize];
629 [dict setObject: [NSNumber numberWithUnsignedLongLong: currInfo->rsrcPhysicalSize] forKey: UKPhysicalResFileSize];
630 }
631 if( UK_BTST(whichInfo, kFSCatInfoFinderXInfo) )
632 {
633 ExtendedFileInfo* xInfo = (ExtendedFileInfo*) currInfo->extFinderInfo;
634
635 if( !UK_BTST(xInfo->extendedFinderFlags, kExtendedFlagsAreInvalid) )
636 {
637 [dict setObject: [NSNumber numberWithBool: UK_BTST(xInfo->extendedFinderFlags, kExtendedFlagHasCustomBadge)] forKey: UKItemHasCustomBadge];
638 [dict setObject: [NSNumber numberWithBool: UK_BTST(xInfo->extendedFinderFlags, kExtendedFlagHasRoutingInfo)] forKey: UKItemHasRoutingInfo];
639 }
640 }
641 if( UK_BTST(whichInfo, kFSCatInfoPermissions) )
642 {
643 FSPermissionInfo* pInfo = (FSPermissionInfo*) currInfo->permissions;
644
645 [dict setObject: [NSNumber numberWithUnsignedLong: pInfo->userID] forKey: NSFileOwnerAccountID];
646 [dict setObject: [NSNumber numberWithUnsignedLong: pInfo->groupID] forKey: NSFileGroupOwnerAccountID];
647 [dict setObject: [NSNumber numberWithUnsignedShort: (pInfo->mode & 0x7FF)] forKey: NSFilePosixPermissions];
648 }
649 CFAbsoluteTime absTime = 0;
650 if( UK_BTST(whichInfo, kFSCatInfoCreateDate) )
651 {
652 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->createDate, &absTime );
653 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: NSFileCreationDate];
654 }
655 if( UK_BTST(whichInfo, kFSCatInfoAttrMod) )
656 {
657 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->attributeModDate, &absTime );
658 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileAttrModificationDate];
659 }
660 if( UK_BTST(whichInfo, kFSCatInfoContentMod) )
661 {
662 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->contentModDate, &absTime );
663 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: NSFileModificationDate];
664 }
665 if( UK_BTST(whichInfo, kFSCatInfoAccessDate) )
666 {
667 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->accessDate, &absTime );
668 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileAccessDate];
669 }
670 if( UK_BTST(whichInfo, kFSCatInfoBackupDate) )
671 {
672 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->backupDate, &absTime );
673 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileBackupDate];
674 }
675
676 return dict;
677 }
678
679
680 void UKFSCatInfoFromDictionary( NSDictionary* attrs, FSCatalogInfo* currInfo, FSCatalogInfoBitmap* whichInfo )
681 {
682 NSNumber* val = nil;
683
684 (*whichInfo) = kFSCatInfoNone;
685 memset( currInfo, 0, sizeof(FSCatalogInfo) ); // Clear all fields.
686
687 // Node Flags:
688 val = [attrs objectForKey: UKItemIsLocked];
689 if( val )
690 {
691 (*whichInfo) |= kFSCatInfoNodeFlags;
692
693 if( [val boolValue] )
694 currInfo->nodeFlags |= kFSNodeLockedMask;
695 }
696
697 // Finder Flags:
698 FileInfo* fInfo = (FileInfo*) currInfo->finderInfo;
699
700 val = [attrs objectForKey: UKItemIsInvisible];
701 if( val )
702 {
703 (*whichInfo) |= kFSCatInfoFinderInfo;
704
705 if( [val boolValue] )
706 fInfo->finderFlags |= kIsInvisible;
707 }
708
709 val = [attrs objectForKey: UKItemIsAlias];
710 if( val )
711 {
712 (*whichInfo) |= kFSCatInfoFinderInfo;
713
714 if( [val boolValue] )
715 fInfo->finderFlags |= kIsAlias;
716 }
717
718 val = [attrs objectForKey: UKItemHasBNDL];
719 if( val )
720 {
721 (*whichInfo) |= kFSCatInfoFinderInfo;
722
723 if( [val boolValue] )
724 fInfo->finderFlags |= kHasBundle;
725 }
726
727 val = [attrs objectForKey: UKItemNameIsLocked];
728 if( val )
729 {
730 (*whichInfo) |= kFSCatInfoFinderInfo;
731
732 if( [val boolValue] )
733 fInfo->finderFlags |= kNameLocked;
734 }
735
736 val = [attrs objectForKey: UKItemIsStationery];
737 if( val )
738 {
739 (*whichInfo) |= kFSCatInfoFinderInfo;
740
741 if( [val boolValue] )
742 fInfo->finderFlags |= kIsStationery;
743 }
744
745 val = [attrs objectForKey: UKItemHasCustomIcon];
746 if( val )
747 {
748 (*whichInfo) |= kFSCatInfoFinderInfo;
749
750 if( [val boolValue] )
751 fInfo->finderFlags |= kHasCustomIcon;
752 }
753
754 val = [attrs objectForKey: UKLabelNumber];
755 if( val )
756 {
757 (*whichInfo) |= kFSCatInfoFinderInfo;
758
759 fInfo->finderFlags |= ([val intValue] << 1) & kColor;
760 }
761
762 val = [attrs objectForKey: NSFileHFSTypeCode];
763 if( val )
764 {
765 (*whichInfo) |= kFSCatInfoFinderInfo;
766 fInfo->fileType = [val unsignedLongValue];
767 }
768
769 val = [attrs objectForKey: NSFileHFSCreatorCode];
770 if( val )
771 {
772 (*whichInfo) |= kFSCatInfoFinderInfo;
773 fInfo->fileCreator = [val unsignedLongValue];
774 }
775
776 // Extended Finder Flags:
777 ExtendedFileInfo* xInfo = (ExtendedFileInfo*) currInfo->extFinderInfo;
778
779 val = [attrs objectForKey: UKItemHasCustomBadge];
780 if( val )
781 {
782 (*whichInfo) |= kFSCatInfoFinderXInfo;
783
784 if( [val boolValue] )
785 xInfo->extendedFinderFlags |= kExtendedFlagHasCustomBadge;
786 }
787
788 val = [attrs objectForKey: UKItemHasRoutingInfo];
789 if( val )
790 {
791 (*whichInfo) |= kFSCatInfoFinderXInfo;
792
793 if( [val boolValue] )
794 xInfo->extendedFinderFlags |= kExtendedFlagHasRoutingInfo;
795 }
796
797 // Permissions:
798 FSPermissionInfo* pInfo = (FSPermissionInfo*) currInfo->permissions;
799
800 val = [attrs objectForKey: NSFileOwnerAccountID];
801 if( val )
802 {
803 (*whichInfo) |= kFSCatInfoPermissions;
804
805 pInfo->userID = [val unsignedLongValue];
806 }
807
808 val = [attrs objectForKey: NSFileGroupOwnerAccountID];
809 if( val )
810 {
811 (*whichInfo) |= kFSCatInfoPermissions;
812
813 pInfo->groupID = [val unsignedLongValue];
814 }
815
816 val = [attrs objectForKey: NSFilePosixPermissions];
817 if( val )
818 {
819 (*whichInfo) |= kFSCatInfoPermissions;
820
821 pInfo->mode = [val unsignedShortValue];
822 }
823
824 // Dates:
825 // TO DO: Write code to set dates.
826 /*CFAbsoluteTime absTime = 0;
827 if( UK_BTST(whichInfo, kFSCatInfoCreateDate) )
828 {
829 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->createDate, &absTime );
830 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: NSFileCreationDate];
831 }
832 if( UK_BTST(whichInfo, kFSCatInfoAttrMod) )
833 {
834 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->attributeModDate, &absTime );
835 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileAttrModificationDate];
836 }
837 if( UK_BTST(whichInfo, kFSCatInfoContentMod) )
838 {
839 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->contentModDate, &absTime );
840 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: NSFileModificationDate];
841 }
842 if( UK_BTST(whichInfo, kFSCatInfoAccessDate) )
843 {
844 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->accessDate, &absTime );
845 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileAccessDate];
846 }
847 if( UK_BTST(whichInfo, kFSCatInfoBackupDate) )
848 {
849 UCConvertUTCDateTimeToCFAbsoluteTime( &currInfo->backupDate, &absTime );
850 [dict setObject: [NSDate dateWithTimeIntervalSinceReferenceDate: absTime] forKey: UKFileBackupDate];
851 }*/
852 }
853
854
Something went wrong with that request. Please try again.