]> git.saurik.com Git - apple/xnu.git/blob - bsd/hfs/hfscommon/Catalog/CatalogIterators.c
xnu-344.23.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Catalog / CatalogIterators.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 File: CatalogIterators.c
24
25 Contains: Catalog Iterator Implementation
26
27 Version: HFS Plus 1.0
28
29 Copyright: © 1997-1998 by Apple Computer, Inc., all rights reserved.
30
31 File Ownership:
32
33 DRI: Don Brady
34
35 Other Contact: Mark Day
36
37 Technology: Mac OS File System
38
39 Writers:
40
41 (msd) Mark Day
42 (djb) Don Brady
43
44 Change History (most recent first):
45 <MacOSX> 4/23/98 djb Re-enable InvalidateCatalogCache (was commented out).
46 <MacOSX> 4/6/98 djb Add locking for cache globals (list) and iterators.
47 <MacOSX> 4/2/98 djb Define gCatalogCacheGlobals here instead of FSVars.
48 <MacOSX> 3/31/98 djb Sync up with final HFSVolumes.h header file.
49
50 <CS3> 11/13/97 djb Radar #1683572 - Fix for indexed GetFileInfo.
51 <CS2> 10/17/97 msd Bug 1683506. Add support for long Unicode names in
52 CatalogIterators. Added a single global buffer for long Unicode
53 names; it is used by at most one CatalogIterator at a time.
54 <CS1> 10/1/97 djb first checked in
55 */
56
57
58 #include "../../hfs_macos_defs.h"
59 #include "../../hfs.h"
60 #include "../../hfs_dbg.h"
61 #include "../../hfs_format.h"
62
63 #include "../headers/FileMgrInternal.h"
64 #include "../headers/BTreesInternal.h"
65 #include "../headers/CatalogPrivate.h"
66
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <libkern/libkern.h>
71 #include <sys/lock.h>
72
73 static void InsertCatalogIteratorAsMRU( CatalogCacheGlobals *cacheGlobals, CatalogIterator *iterator );
74
75 static void InsertCatalogIteratorAsLRU( CatalogCacheGlobals *cacheGlobals, CatalogIterator *iterator );
76
77 static void PrepareForLongName( CatalogIterator *iterator );
78
79
80 #if TARGET_API_MACOS_X
81 CatalogCacheGlobals *gCatalogCacheGlobals;
82
83 #define GetCatalogCacheGlobals() (gCatalogCacheGlobals)
84
85 #define CATALOG_ITER_LIST_LOCK(g) simple_lock(&(g)->simplelock)
86
87 #define CATALOG_ITER_LIST_UNLOCK(g) simple_unlock(&(g)->simplelock)
88
89 #define CI_LOCK(i) lockmgr(&(i)->iterator_lock, LK_EXCLUSIVE, (simple_lock_t) 0, current_proc())
90
91 #define CI_UNLOCK(i) lockmgr(&(i)->iterator_lock, LK_RELEASE, (simple_lock_t) 0, current_proc())
92
93 #define CI_SLEEPLESS_LOCK(i) lockmgr(&(i)->iterator_lock, LK_EXCLUSIVE | LK_NOWAIT, (simple_lock_t) 0, current_proc())
94
95 #define CI_LOCK_FROM_LIST(g,i) lockmgr(&(i)->iterator_lock, LK_EXCLUSIVE | LK_INTERLOCK, &(g)->simplelock, current_proc())
96
97 #else /* TARGET_API_MACOS_X */
98
99 #define GetCatalogCacheGlobals() ((CatalogCacheGlobals*) ((FSVarsRec*) LMGetFSMVars()->gCatalogCacheGlobals))
100
101 #define CATALOG_ITER_LIST_LOCK(g)
102
103 #define CATALOG_ITER_LIST_UNLOCK(g)
104
105 #define CI_LOCK(i) 0
106
107 #define CI_UNLOCK(i) 0
108
109 #define CI_SLEEPLESS_LOCK(i) 0
110
111 #define CI_LOCK_FROM_LIST(g,i) 0
112
113 #endif
114
115
116 //_______________________________________________________________________________
117 // Routine: InitCatalogCache
118 //
119 // Function: Allocates cache, and initializes all the cache structures.
120 //
121 //_______________________________________________________________________________
122 OSErr
123 InitCatalogCache(void)
124 {
125 CatalogCacheGlobals * cacheGlobals;
126 CatalogIterator * iterator;
127 UInt32 cacheSize;
128 UInt16 i;
129 UInt16 lastIterator;
130 OSErr err;
131
132
133 cacheSize = sizeof(CatalogCacheGlobals) + ( kCatalogIteratorCount * sizeof(CatalogIterator) );
134 cacheGlobals = (CatalogCacheGlobals *) NewPtrSysClear( cacheSize );
135
136 cacheGlobals->iteratorCount = kCatalogIteratorCount;
137
138 lastIterator = kCatalogIteratorCount - 1; // last iterator number, since they start at 0
139
140 // Initialize the MRU order for the cache
141 cacheGlobals->mru = (CatalogIterator *) ( (Ptr)cacheGlobals + sizeof(CatalogCacheGlobals) );
142
143 // Initialize the LRU order for the cache
144 cacheGlobals->lru = (CatalogIterator *) ( (Ptr)(cacheGlobals->mru) + (lastIterator * sizeof(CatalogIterator)) );
145
146
147 // Traverse iterators, setting initial mru, lru, and default values
148 for ( i = 0, iterator = cacheGlobals->mru; i < kCatalogIteratorCount ; i++, iterator = iterator->nextMRU )
149 {
150 if ( i == lastIterator )
151 iterator->nextMRU = nil; // terminate the list
152 else
153 iterator->nextMRU = (CatalogIterator *) ( (Ptr)iterator + sizeof(CatalogIterator) );
154
155 if ( i == 0 )
156 iterator->nextLRU = nil; // terminate the list
157 else
158 iterator->nextLRU = (CatalogIterator *) ( (Ptr)iterator - sizeof(CatalogIterator) );
159
160 #if TARGET_API_MACOS_X
161 lockinit(&iterator->iterator_lock, PINOD, "hfs_catalog_iterator", 0, 0);
162 #endif
163 }
164
165 #if TARGET_API_MAC_OS8
166 (FSVarsRec*) LMGetFSMVars()->gCatalogCacheGlobals = (Ptr) cacheGlobals;
167 #endif
168
169 #if TARGET_API_MACOS_X
170 gCatalogCacheGlobals = cacheGlobals;
171 simple_lock_init(&cacheGlobals->simplelock);
172 #endif
173
174 return noErr;
175 }
176
177
178 //_______________________________________________________________________________
179 // Routine: InvalidateCatalogCache
180 //
181 // Function: Trash any interators matching volume parameter
182 //
183 //_______________________________________________________________________________
184 void PrintCatalogIterator( void );
185
186 void
187 InvalidateCatalogCache( ExtendedVCB *volume )
188 {
189 TrashCatalogIterator( volume, 0 );
190 }
191
192
193 //_______________________________________________________________________________
194 // Routine: PrintCatalogIterator
195 //
196 // Function: Prints all interators
197 //
198 //_______________________________________________________________________________
199 #if HFS_DIAGNOSTIC
200 void
201 PrintCatalogIterator( void )
202 {
203 CatalogIterator *iterator;
204 CatalogCacheGlobals *cacheGlobals = GetCatalogCacheGlobals();
205 int i;
206
207 PRINTIT("CatalogCacheGlobals @ 0x%08lX are:\n", (unsigned long)cacheGlobals);
208 PRINTIT("\titeratorCount: %ld \n", cacheGlobals->iteratorCount);
209 PRINTIT("\tmru: 0x%08lX \n", (unsigned long)cacheGlobals->mru);
210 PRINTIT("\tlru: 0x%08lX \n", (unsigned long)cacheGlobals->lru);
211
212 for ( iterator = cacheGlobals->mru, i=0 ; iterator != nil && i<32 ; iterator = iterator->nextMRU, i++)
213 {
214 PRINTIT("%d: ", i);
215 PRINTIT(" i: 0x%08lX", (unsigned long)iterator);
216 PRINTIT(" M: 0x%08lX", (unsigned long)iterator->nextMRU);
217 PRINTIT(" L: 0x%08lX", (unsigned long)iterator->nextLRU);
218 PRINTIT("\n");
219 }
220 }
221 #endif
222
223 //_______________________________________________________________________________
224 // Routine: TrashCatalogIterator
225 //
226 // Function: Trash any interators matching volume and folder parameters
227 //
228 //_______________________________________________________________________________
229 void
230 TrashCatalogIterator( const ExtendedVCB *volume, HFSCatalogNodeID folderID )
231 {
232 CatalogIterator *iterator;
233 CatalogCacheGlobals *cacheGlobals = GetCatalogCacheGlobals();
234
235 CATALOG_ITER_LIST_LOCK(cacheGlobals);
236
237 for ( iterator = cacheGlobals->mru ; iterator != nil ; iterator = iterator->nextMRU )
238 {
239 top:
240
241 // first match the volume
242 if ( iterator->volume != volume )
243 continue;
244
245 // now match the folder (or all folders if 0)
246 if ( (folderID == 0) || (folderID == iterator->folderID) )
247 {
248 CatalogIterator *next;
249
250 iterator->volume = 0; // trash it
251 iterator->folderID = 0;
252
253 next = iterator->nextMRU; // remember the next iterator
254
255 // if iterator is not already last then make it last
256 if ( next != nil )
257 {
258 InsertCatalogIteratorAsLRU( cacheGlobals, iterator );
259
260 // iterator->nextMRU will always be zero (since we moved it to the end)
261 // so set up the next iterator manually (we know its not nil)
262 iterator = next;
263 goto top; // process the next iterator
264 }
265 }
266 }
267
268 CATALOG_ITER_LIST_UNLOCK(cacheGlobals);
269 }
270
271
272 //_______________________________________________________________________________
273 // Routine: AgeCatalogIterator
274 //
275 // Function: Move iterator to the end of the list...
276 //
277 //_______________________________________________________________________________
278 void
279 AgeCatalogIterator ( CatalogIterator *catalogIterator )
280 {
281 CatalogCacheGlobals * cacheGlobals = GetCatalogCacheGlobals();
282
283 CATALOG_ITER_LIST_LOCK(cacheGlobals);
284
285 //PRINTIT(" AgeCatalogIterator: v=%d, d=%ld, i=%d\n", catalogIterator->volRefNum, catalogIterator->folderID, catalogIterator->currentIndex);
286
287 InsertCatalogIteratorAsLRU( cacheGlobals, catalogIterator );
288
289 CATALOG_ITER_LIST_UNLOCK(cacheGlobals);
290 }
291
292
293 //_______________________________________________________________________________
294 // Routine: GetCatalogIterator
295 //
296 // Function: Release interest in Catalog iterator
297 //
298 //_______________________________________________________________________________
299 OSErr
300 ReleaseCatalogIterator( CatalogIterator* catalogIterator)
301 {
302 #if TARGET_API_MACOS_X
303 //PRINTIT(" ReleaseCatalogIterator: v=%d, d=%ld, i=%d\n", catalogIterator->volRefNum, catalogIterator->folderID, catalogIterator->currentIndex);
304 return CI_UNLOCK(catalogIterator);
305 #else
306 return noErr;
307 #endif
308 }
309
310
311 //_______________________________________________________________________________
312 // Routine: GetCatalogIterator
313 //
314 // Function: Returns an iterator associated with the volume, folderID, index,
315 // and iterationType (kIterateFilesOnly or kIterateAll).
316 // Searches the cache in MRU order.
317 // Inserts the resulting iterator at the head of mru automatically
318 //
319 // Note: The returned iterator is locked and ReleaseCatalogIterator must
320 // be called to unlock it.
321 //
322 //_______________________________________________________________________________
323
324 CatalogIterator*
325 GetCatalogIterator(ExtendedVCB *volume, HFSCatalogNodeID folderID, UInt32 offset)
326 {
327 CatalogCacheGlobals *cacheGlobals = GetCatalogCacheGlobals();
328 CatalogIterator *iterator;
329 CatalogIterator *bestIterator;
330
331 bestIterator = NULL;
332
333 CATALOG_ITER_LIST_LOCK(cacheGlobals);
334
335 for (iterator = cacheGlobals->mru ; iterator != nil ; iterator = iterator->nextMRU) {
336
337 /* first make sure volume and folder id match */
338 if ((iterator->volume != volume) || (iterator->folderID != folderID)) {
339 continue;
340 }
341
342 /* ignore busy iterators */
343 if ( CI_SLEEPLESS_LOCK(iterator) == EBUSY ) {
344 //PRINTIT(" GetCatalogIterator: busy v=%d, d=%ld, i=%d\n", volume, folderID, iterator->currentIndex);
345 continue;
346 }
347
348 /* we matched volume, folder id, now check the offset */
349 if ( iterator->currentOffset == offset || iterator->nextOffset == offset) {
350 bestIterator = iterator; // we scored! - so get out of this loop
351 break; // break with iterator locked
352 }
353
354 (void) CI_UNLOCK(iterator); // unlock iterator before moving to the next one
355 }
356
357 // check if we didn't get one or if the one we got is too far away...
358 if (bestIterator == NULL)
359 {
360 bestIterator = cacheGlobals->lru; // start over with a new iterator
361
362 //PRINTIT(" GetCatalogIterator: recycle v=%d, d=%ld, i=%d\n", bestIterator->volume, bestIterator->folderID, bestIterator->currentIndex);
363 (void) CI_LOCK_FROM_LIST(cacheGlobals, bestIterator); // XXX we should not eat the error!
364
365 CATALOG_ITER_LIST_LOCK(cacheGlobals); // grab the lock again for MRU Insert below...
366
367 bestIterator->volume = volume; // update the iterator's volume
368 bestIterator->folderID = folderID; // ... and folderID
369 bestIterator->currentIndex = 0xFFFFFFFF; // ... and offspring index marker
370 bestIterator->currentOffset = 0xFFFFFFFF;
371 bestIterator->nextOffset = 0xFFFFFFFF;
372
373 bestIterator->btreeNodeHint = 0;
374 bestIterator->btreeIndexHint = 0;
375 bestIterator->parentID = folderID; // set key to folderID + empty name
376 bestIterator->folderName.unicodeName.length = 0; // clear pascal/unicode name
377
378 if ( volume->vcbSigWord == kHFSPlusSigWord )
379 bestIterator->nameType = kShortUnicodeName;
380 else
381 bestIterator->nameType = kShortPascalName;
382 }
383 else {
384 //PRINTIT(" GetCatalogIterator: found v=%d, d=%ld, i=%d\n", bestIterator->volume, bestIterator->folderID, bestIterator->currentIndex);
385 }
386
387 // put this iterator at the front of the list
388 InsertCatalogIteratorAsMRU( cacheGlobals, bestIterator );
389
390 CATALOG_ITER_LIST_UNLOCK(cacheGlobals);
391
392 return bestIterator; // return our best shot
393
394 } /* GetCatalogIterator */
395
396
397 //_______________________________________________________________________________
398 // Routine: UpdateBtreeIterator
399 //
400 // Function: Fills in a BTreeIterator from a CatalogIterator
401 //
402 // Assumes: catalogIterator->nameType is correctly initialized!
403 // catalogIterator is locked (MacOS X)
404 //_______________________________________________________________________________
405 void
406 UpdateBtreeIterator(const CatalogIterator *catalogIterator, BTreeIterator *btreeIterator)
407 {
408 CatalogName * nodeName;
409 Boolean isHFSPlus;
410
411
412 btreeIterator->hint.writeCount = 0;
413 btreeIterator->hint.nodeNum = catalogIterator->btreeNodeHint;
414 btreeIterator->hint.index = catalogIterator->btreeIndexHint;
415
416 switch (catalogIterator->nameType)
417 {
418 case kShortPascalName:
419 if ( catalogIterator->folderName.pascalName[0] > 0 )
420 nodeName = (CatalogName *) catalogIterator->folderName.pascalName;
421 else
422 nodeName = NULL;
423
424 isHFSPlus = false;
425 break;
426
427 case kShortUnicodeName:
428 if ( catalogIterator->folderName.unicodeName.length > 0 )
429 nodeName = (CatalogName *) &catalogIterator->folderName.unicodeName;
430 else
431 nodeName = NULL;
432
433 isHFSPlus = true;
434 break;
435
436 case kLongUnicodeName:
437 if ( catalogIterator->folderName.longNamePtr->length > 0 )
438 nodeName = (CatalogName *) catalogIterator->folderName.longNamePtr;
439 else
440 nodeName = NULL;
441
442 isHFSPlus = true;
443 break;
444
445 default:
446 return;
447 }
448
449 BuildCatalogKey(catalogIterator->parentID, nodeName, isHFSPlus, (CatalogKey*) &btreeIterator->key);
450 }
451
452
453 //_______________________________________________________________________________
454 // Routine: UpdateCatalogIterator
455 //
456 // Function: Updates a CatalogIterator from a BTreeIterator
457 //
458 // Assumes: catalogIterator->nameType is correctly initialized!
459 // catalogIterator is locked (MacOS X)
460 //_______________________________________________________________________________
461 void
462 UpdateCatalogIterator (const BTreeIterator *btreeIterator, CatalogIterator *catalogIterator)
463 {
464 void * srcName;
465 void * dstName;
466 UInt16 nameSize;
467 CatalogKey * catalogKey;
468
469
470 catalogIterator->btreeNodeHint = btreeIterator->hint.nodeNum;
471 catalogIterator->btreeIndexHint = btreeIterator->hint.index;
472
473 catalogKey = (CatalogKey*) &btreeIterator->key;
474
475 switch (catalogIterator->nameType)
476 {
477 case kShortPascalName:
478 catalogIterator->parentID = catalogKey->hfs.parentID;
479
480 dstName = catalogIterator->folderName.pascalName;
481 srcName = catalogKey->hfs.nodeName;
482 nameSize = catalogKey->hfs.nodeName[0] + sizeof(UInt8);
483 break;
484
485 case kShortUnicodeName:
486 catalogIterator->parentID = catalogKey->hfsPlus.parentID;
487
488 dstName = &catalogIterator->folderName.unicodeName;
489 srcName = &catalogKey->hfsPlus.nodeName;
490 nameSize = (catalogKey->hfsPlus.nodeName.length + 1) * sizeof(UInt16);
491
492 // See if we need to make this iterator use long names
493 if ( nameSize > sizeof(catalogIterator->folderName.unicodeName) )
494 {
495 PrepareForLongName(catalogIterator); // Find a long name buffer to use
496 dstName = catalogIterator->folderName.longNamePtr;
497 }
498 break;
499
500 case kLongUnicodeName:
501 catalogIterator->parentID = catalogKey->hfsPlus.parentID;
502
503 dstName = catalogIterator->folderName.longNamePtr;
504 srcName = &catalogKey->hfsPlus.nodeName;
505 nameSize = (catalogKey->hfsPlus.nodeName.length + 1) * sizeof(UInt16);
506 break;
507
508 default:
509 return;
510 }
511
512 if (catalogIterator->parentID != catalogIterator->folderID)
513 catalogIterator->nextOffset = 0xFFFFFFFF;
514
515 BlockMoveData(srcName, dstName, nameSize);
516
517 } // end UpdateCatalogIterator
518
519
520 //_______________________________________________________________________________
521 // Routine: InsertCatalogIteratorAsMRU
522 //
523 // Function: Moves catalog iterator to head of mru order in double linked list
524 //
525 // Assumes list simple lock is held
526 //_______________________________________________________________________________
527 static void
528 InsertCatalogIteratorAsMRU ( CatalogCacheGlobals *cacheGlobals, CatalogIterator *iterator )
529 {
530 CatalogIterator *swapIterator;
531
532 if ( cacheGlobals->mru != iterator ) // if it's not already the mru iterator
533 {
534 swapIterator = cacheGlobals->mru; // put it in the front of the double queue
535 cacheGlobals->mru = iterator;
536 iterator->nextLRU->nextMRU = iterator->nextMRU;
537 if ( iterator->nextMRU != nil )
538 iterator->nextMRU->nextLRU = iterator->nextLRU;
539 else
540 cacheGlobals->lru= iterator->nextLRU;
541 iterator->nextMRU = swapIterator;
542 iterator->nextLRU = nil;
543 swapIterator->nextLRU = iterator;
544 }
545 }
546
547
548 //________________________________________________________________________________
549 // Routine: InsertCatalogIteratorAsLRU
550 //
551 // Function: Moves catalog iterator to head of lru order in double linked list
552 //
553 // Assumes list simple lock is held
554 //_______________________________________________________________________________
555 static void
556 InsertCatalogIteratorAsLRU ( CatalogCacheGlobals *cacheGlobals, CatalogIterator *iterator )
557 {
558 CatalogIterator *swapIterator;
559
560 if ( cacheGlobals->lru != iterator )
561 {
562 swapIterator = cacheGlobals->lru;
563 cacheGlobals->lru = iterator;
564 iterator->nextMRU->nextLRU = iterator->nextLRU;
565 if ( iterator->nextLRU != nil )
566 iterator->nextLRU->nextMRU = iterator->nextMRU;
567 else
568 cacheGlobals->mru= iterator->nextMRU;
569 iterator->nextLRU = swapIterator;
570 iterator->nextMRU = nil;
571 swapIterator->nextMRU = iterator;
572 }
573 }
574
575
576
577 //_______________________________________________________________________________
578 // Routine: PrepareForLongName
579 //
580 // Function: Takes a CatalogIterator whose nameType is kShortUnicodeName, and
581 // changes the nameType to kLongUnicodeName.
582 //
583 // Since long Unicode names aren't stored in the CatalogIterator itself, we have
584 // to point to an HFSUniStr255 for storage. In the current implementation, we have
585 // just one such global buffer in the cache globals. We'll set the iterator to
586 // point to the global buffer and invalidate the iterator that was using it
587 // (i.e. the iterator whose nameType is kLongUnicodeName).
588 //
589 // Eventually, we might want to have a list of long name buffers which we recycle
590 // using an LRU algorithm. Or perhaps, some other way....
591 //
592 // Assumes: catalogIterator is locked (MacOS X)
593 //_______________________________________________________________________________
594 static void
595 PrepareForLongName ( CatalogIterator *iterator )
596 {
597 CatalogCacheGlobals *cacheGlobals = GetCatalogCacheGlobals();
598 CatalogIterator *iter;
599
600 if (DEBUG_BUILD && iterator->nameType != kShortUnicodeName)
601 DebugStr("\p PrepareForLongName: nameType is wrong!");
602
603 //
604 // Walk through all the iterators. The first iterator whose nameType
605 // is kLongUnicodeName is invalidated (because it is using the global
606 // long name buffer).
607 //
608
609 CATALOG_ITER_LIST_LOCK(cacheGlobals);
610
611 for ( iter = cacheGlobals->mru ; iter != nil ; iter = iter->nextMRU )
612 {
613 if (iter->nameType == kLongUnicodeName)
614 {
615 // if iterator is not already last then make it last
616 if ( iter->nextMRU != nil )
617 InsertCatalogIteratorAsLRU( cacheGlobals, iter );
618
619 (void) CI_LOCK_FROM_LIST(cacheGlobals,iter);
620 iter->volume = 0; // trash it
621 iter->folderID = 0;
622 (void) CI_UNLOCK(iter);
623
624 #if TARGET_API_MACOS_X
625 break;
626 #endif
627 }
628 }
629
630 /*
631 * if iter is nil then none of the iterators was using the LongUnicodeName buffer
632 */
633 if (iter == nil)
634 CATALOG_ITER_LIST_UNLOCK(cacheGlobals);
635
636 //
637 // Change the nameType of this iterator and point to the global
638 // long name buffer. Note - this iterator is already locked
639 //
640 iterator->nameType = kLongUnicodeName;
641 iterator->folderName.longNamePtr = &cacheGlobals->longName;
642 }
643